Merge "Performance improvements for measure pass." into androidx-master-dev am: dda4893b77
Change-Id: I4df26291f5f46c3f27544efa31ac78102e5315e5
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt b/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt
index b9a83b6..ce0c1e3a 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt
@@ -16,6 +16,7 @@
package androidx.animation
+import androidx.ui.util.fastFirstOrNull
import kotlin.experimental.ExperimentalTypeInference
/**
@@ -269,10 +270,10 @@
}
internal fun getSpec(fromState: T, toState: T): TransitionSpec<T> {
- return transitionSpecs.firstOrNull { it.defines(fromState, toState) }
- ?: transitionSpecs.firstOrNull { it.defines(fromState, null) }
- ?: transitionSpecs.firstOrNull { it.defines(null, toState) }
- ?: transitionSpecs.firstOrNull { it.defines(null, null) }
+ return transitionSpecs.fastFirstOrNull { it.defines(fromState, toState) }
+ ?: transitionSpecs.fastFirstOrNull { it.defines(fromState, null) }
+ ?: transitionSpecs.fastFirstOrNull { it.defines(null, toState) }
+ ?: transitionSpecs.fastFirstOrNull { it.defines(null, null) }
?: defaultTransitionSpec
}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/ComponentNodes.kt b/ui/ui-core/src/main/java/androidx/ui/core/ComponentNodes.kt
index 1984062..32f1d67 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/ComponentNodes.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/ComponentNodes.kt
@@ -680,6 +680,19 @@
private var outerZIndexModifier: ZIndexModifier? = null
/**
+ * The inner-most layer wrapper. Used for performance for LayoutNodeWrapper.findLayer().
+ */
+ internal var innerLayerWrapper: LayerWrapper? = null
+
+ /**
+ * Returns the inner-most layer as part of this LayoutNode or from the containing LayoutNode.
+ * This is added for performance so that LayoutNodeWrapper.findLayer() can be faster.
+ */
+ internal fun findLayer(): OwnedLayer? {
+ return innerLayerWrapper?.layer ?: parentLayoutNode?.findLayer()
+ }
+
+ /**
* The [Modifier] currently applied to this node.
*/
var modifier: Modifier = Modifier
@@ -693,6 +706,7 @@
onPositionedCallbacks.clear()
onChildPositionedCallbacks.clear()
outerZIndexModifier = null
+ innerLayerWrapper = null
layoutNodeWrapper = modifier.foldOut(innerLayoutNodeWrapper) { mod, toWrap ->
var wrapper = toWrap
// The order in which the following blocks occur matters. For example, the
@@ -709,7 +723,11 @@
wrapper = ModifiedDrawNode(wrapper, mod)
}
if (mod is DrawLayerModifier) {
- wrapper = LayerWrapper(wrapper, mod)
+ val layerWrapper = LayerWrapper(wrapper, mod)
+ wrapper = layerWrapper
+ if (innerLayerWrapper == null) {
+ innerLayerWrapper = layerWrapper
+ }
}
if (mod is FocusModifier) {
require(mod is FocusModifierImpl)
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt b/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
index a99f63e..0e6d8ca 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
@@ -28,6 +28,7 @@
import androidx.ui.unit.PxPosition
import androidx.ui.unit.toPxSize
import androidx.ui.util.fastAny
+import androidx.ui.util.fastFirstOrNull
import androidx.ui.util.fastForEach
internal class InnerPlaceable(
@@ -62,7 +63,7 @@
null
} else {
layoutNode.layoutChildren
- .firstOrNull { it.parentData != null }?.parentData
+ .fastFirstOrNull { it.parentData != null }?.parentData
}
override fun findFocusWrapperWrappingThisWrapper() =
@@ -186,4 +187,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt b/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
index ff348cc..47c2b40 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
@@ -36,6 +36,7 @@
import androidx.ui.unit.ipx
import androidx.ui.unit.max
import androidx.ui.unit.min
+import androidx.ui.util.fastForEach
/**
* [Layout] is the main core component for layout. It can be used to measure and position
@@ -199,7 +200,7 @@
val width = placeables.maxBy { it.width }?.width ?: constraints.minWidth
val height = placeables.maxBy { it.height }?.height ?: constraints.minHeight
layout(width, height) {
- placeables.forEach { it.place(IntPx.Zero, IntPx.Zero) }
+ placeables.fastForEach { it.place(IntPx.Zero, IntPx.Zero) }
}
}
MeasuringIntrinsicsMeasureBlocks(measureBlock)
@@ -568,7 +569,7 @@
val layoutChildren = root.layoutChildren
var maxWidth: IntPx = constraints.minWidth
var maxHeight: IntPx = constraints.minHeight
- layoutChildren.forEach {
+ layoutChildren.fastForEach {
it.measure(constraints, layoutDirection)
maxWidth = max(maxWidth, it.width)
maxHeight = max(maxHeight, it.height)
@@ -577,7 +578,7 @@
maxHeight = min(maxHeight, constraints.maxHeight)
return measureScope.layout(maxWidth, maxHeight) {
- layoutChildren.forEach { it.place(IntPx.Zero, IntPx.Zero) }
+ layoutChildren.fastForEach { it.place(IntPx.Zero, IntPx.Zero) }
}
}
}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
index bc2fe55..b660d948 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
@@ -290,7 +290,13 @@
/**
* Returns the layer that this wrapper will draw into.
*/
- open fun findLayer(): OwnedLayer? = wrappedBy?.findLayer()
+ open fun findLayer(): OwnedLayer? {
+ return if (layoutNode.innerLayerWrapper != null) {
+ wrappedBy?.findLayer()
+ } else {
+ layoutNode.findLayer()
+ }
+ }
/**
* Returns the first [ModifiedFocusNode] in the wrapper list that wraps this
diff --git a/ui/ui-core/src/main/java/androidx/ui/node/ViewInterop.kt b/ui/ui-core/src/main/java/androidx/ui/node/ViewInterop.kt
index 8985b93..7bd8279 100644
--- a/ui/ui-core/src/main/java/androidx/ui/node/ViewInterop.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/node/ViewInterop.kt
@@ -32,6 +32,7 @@
import androidx.ui.unit.IntPx
import androidx.ui.unit.ipx
import androidx.ui.unit.isFinite
+import androidx.ui.util.fastFirstOrNull
import androidx.ui.viewinterop.AndroidViewHolder
/**
@@ -157,7 +158,7 @@
inline fun <T : ViewAdapter> get(id: Int, factory: () -> T): T {
@Suppress("UNCHECKED_CAST")
- val existing = adapters.firstOrNull { it.id == id } as? T
+ val existing = adapters.fastFirstOrNull { it.id == id } as? T
if (existing != null) return existing
val next = factory()
adapters.add(next)
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt b/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
index 1b94655..375390a 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
@@ -67,6 +67,7 @@
import androidx.ui.unit.max
import androidx.ui.unit.sp
import androidx.ui.unit.toPx
+import androidx.ui.util.fastFirstOrNull
/**
* A TabRow contains a row of [Tab]s, and displays an indicator underneath the currently
@@ -285,13 +286,13 @@
// The divider is measured with its own height, and width equal to the total width
// of the tab row, and then placed on top of the tabs.
- measurables.firstOrNull { it.tag == dividerTag }
+ measurables.fastFirstOrNull { it.tag == dividerTag }
?.measure(constraints.copy(minWidth = layoutWidth, maxWidth = layoutWidth))
?.run { place(IntPx.Zero, layoutHeight - height) }
// The indicator container is measured to fill the entire space occupied by the tab
// row, and then placed on top of the divider.
- measurables.firstOrNull { it.tag == indicatorTag }
+ measurables.fastFirstOrNull { it.tag == indicatorTag }
?.measure(Constraints.fixed(layoutWidth, layoutHeight))
?.place(IntPx.Zero, IntPx.Zero)
}
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt b/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
index 3b2f6c0..6758f33 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
@@ -30,6 +30,7 @@
import androidx.ui.foundation.animation.fling
import androidx.ui.foundation.gestures.DragDirection
import androidx.ui.foundation.gestures.draggable
+import androidx.ui.util.fastFirstOrNull
/**
* Higher-level component that allows dragging around anchored positions binded to different states
@@ -74,7 +75,7 @@
val forceAnimationCheck = state { true }
val anchors = remember(anchorsToState) { anchorsToState.map { it.first } }
- val currentValue = anchorsToState.firstOrNull { it.second == state }!!.first
+ val currentValue = anchorsToState.fastFirstOrNull { it.second == state }!!.first
val flingConfig =
AnchorsFlingConfig(anchors, animationBuilder, onAnimationEnd = { reason, finalValue, _ ->
if (reason != AnimationEndReason.Interrupted) {
diff --git a/ui/ui-text-core/api/0.1.0-dev12.txt b/ui/ui-text-core/api/0.1.0-dev12.txt
index 946c57b..d08cf00 100644
--- a/ui/ui-text-core/api/0.1.0-dev12.txt
+++ b/ui/ui-text-core/api/0.1.0-dev12.txt
@@ -413,7 +413,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/current.txt b/ui/ui-text-core/api/current.txt
index 946c57b..d08cf00 100644
--- a/ui/ui-text-core/api/current.txt
+++ b/ui/ui-text-core/api/current.txt
@@ -413,7 +413,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev12.txt
index 946c57b..d08cf00 100644
--- a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev12.txt
@@ -413,7 +413,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/public_plus_experimental_current.txt b/ui/ui-text-core/api/public_plus_experimental_current.txt
index 946c57b..d08cf00 100644
--- a/ui/ui-text-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_current.txt
@@ -413,7 +413,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/restricted_0.1.0-dev12.txt b/ui/ui-text-core/api/restricted_0.1.0-dev12.txt
index 07f2f76..6f7ebdd 100644
--- a/ui/ui-text-core/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-text-core/api/restricted_0.1.0-dev12.txt
@@ -418,7 +418,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/restricted_current.txt b/ui/ui-text-core/api/restricted_current.txt
index 07f2f76..6f7ebdd 100644
--- a/ui/ui-text-core/api/restricted_current.txt
+++ b/ui/ui-text-core/api/restricted_current.txt
@@ -418,7 +418,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt b/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt
index 6e4abe5..fe529f3 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt
+++ b/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt
@@ -45,8 +45,8 @@
/* actual */ fun ParagraphIntrinsics(
text: String,
style: TextStyle,
- spanStyles: List<AnnotatedString.Item<SpanStyle>> = listOf(),
- placeholders: List<AnnotatedString.Item<Placeholder>> = listOf(),
+ spanStyles: List<AnnotatedString.Item<SpanStyle>> = emptyList(),
+ placeholders: List<AnnotatedString.Item<Placeholder>> = emptyList(),
density: Density,
resourceLoader: Font.ResourceLoader
): ParagraphIntrinsics {
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt b/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
index 84fc451..2af715f 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
+++ b/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
@@ -65,6 +65,7 @@
import androidx.ui.text.style.TextDecoration
import androidx.ui.text.style.TextDirectionAlgorithm
import androidx.ui.text.style.TextIndent
+import androidx.ui.util.fastForEach
import kotlin.math.ceil
import kotlin.math.roundToInt
import android.os.LocaleList as AndroidLocaleList
@@ -426,7 +427,8 @@
}
}
- for ((placeholder, start, end) in placeholders) {
+ placeholders.fastForEach {
+ val (placeholder, start, end) = it
with(placeholder) {
spannableString.setSpanWithPriority(
PlaceholderSpan(
@@ -531,4 +533,4 @@
PlaceholderVerticalAlign.TextTop -> PlaceholderSpan.ALIGN_TEXT_TOP
PlaceholderVerticalAlign.TextBottom -> PlaceholderSpan.ALIGN_TEXT_BOTTOM
PlaceholderVerticalAlign.TextCenter -> PlaceholderSpan.ALIGN_TEXT_CENTER
- }
\ No newline at end of file
+ }
diff --git a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/TextUnit.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/TextUnit.kt
index 009e06f..d90d823 100644
--- a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/TextUnit.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/TextUnit.kt
@@ -172,6 +172,8 @@
}
companion object {
+ internal val TextUnitTypes = arrayOf(TextUnitType.Inherit, TextUnitType.Sp, TextUnitType.Em)
+
/**
* Creates a SP unit [TextUnit].
*/
@@ -221,12 +223,7 @@
*
* @throws RuntimeException if unknown unknown unit type is appeared.
*/
- val type: TextUnitType get() = when (rawType) {
- UNIT_TYPE_INHERIT -> TextUnitType.Inherit
- UNIT_TYPE_SP -> TextUnitType.Sp
- UNIT_TYPE_EM -> TextUnitType.Em
- else -> throw RuntimeException("packed TextUnit has unknown unit type.")
- }
+ val type: TextUnitType get() = TextUnitTypes[(rawType ushr 32).toInt()]
/**
* True if this is [TextUnit.Inherit], otherwise false.
diff --git a/ui/ui-util/api/0.1.0-dev12.txt b/ui/ui-util/api/0.1.0-dev12.txt
index b30e285..9286e03 100644
--- a/ui/ui-util/api/0.1.0-dev12.txt
+++ b/ui/ui-util/api/0.1.0-dev12.txt
@@ -30,6 +30,7 @@
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
diff --git a/ui/ui-util/api/current.txt b/ui/ui-util/api/current.txt
index b30e285..9286e03 100644
--- a/ui/ui-util/api/current.txt
+++ b/ui/ui-util/api/current.txt
@@ -30,6 +30,7 @@
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
diff --git a/ui/ui-util/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-util/api/public_plus_experimental_0.1.0-dev12.txt
index b30e285..9286e03 100644
--- a/ui/ui-util/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-util/api/public_plus_experimental_0.1.0-dev12.txt
@@ -30,6 +30,7 @@
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
diff --git a/ui/ui-util/api/public_plus_experimental_current.txt b/ui/ui-util/api/public_plus_experimental_current.txt
index b30e285..9286e03 100644
--- a/ui/ui-util/api/public_plus_experimental_current.txt
+++ b/ui/ui-util/api/public_plus_experimental_current.txt
@@ -30,6 +30,7 @@
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
diff --git a/ui/ui-util/api/restricted_0.1.0-dev12.txt b/ui/ui-util/api/restricted_0.1.0-dev12.txt
index b30e285..9286e03 100644
--- a/ui/ui-util/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-util/api/restricted_0.1.0-dev12.txt
@@ -30,6 +30,7 @@
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
diff --git a/ui/ui-util/api/restricted_current.txt b/ui/ui-util/api/restricted_current.txt
index b30e285..9286e03 100644
--- a/ui/ui-util/api/restricted_current.txt
+++ b/ui/ui-util/api/restricted_current.txt
@@ -30,6 +30,7 @@
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
diff --git a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
index f032a4f..cc900d5 100644
--- a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
@@ -34,3 +34,11 @@
fastForEach { if (predicate(it)) return true }
return false
}
+
+/**
+ * Returns the first value that [predicate] returns `true` for or `null` if nothing matches.
+ */
+inline fun <T> List<T>.fastFirstOrNull(predicate: (T) -> Boolean): T? {
+ fastForEach { if (predicate(it)) return it }
+ return null
+}
\ No newline at end of file
diff --git a/ui/ui-util/src/unitTest/kotlin/androidx/ui/util/ListUtilsTest.kt b/ui/ui-util/src/unitTest/kotlin/androidx/ui/util/ListUtilsTest.kt
index 8d1ae60..46ae408 100644
--- a/ui/ui-util/src/unitTest/kotlin/androidx/ui/util/ListUtilsTest.kt
+++ b/ui/ui-util/src/unitTest/kotlin/androidx/ui/util/ListUtilsTest.kt
@@ -18,6 +18,7 @@
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
@@ -69,4 +70,15 @@
val list = listOf(0, -1, -500, 1)
assertTrue(list.fastAny { it > 0 })
}
+
+ @Test
+ fun firstOrNullNotFound() {
+ val list = listOf(0, -1, -500)
+ assertNull(list.fastFirstOrNull { it > 0 })
+ }
+ @Test
+ fun firstOrNullFound() {
+ val list = listOf(0, -1, -500, 1)
+ assertEquals(1, list.fastFirstOrNull { it > 0 })
+ }
}
\ No newline at end of file