Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ecab7cf authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Annotate Stable classes/interfaces to optimize compositions

This CL annotates most of the public STL classes as @Stable (which they
are) so that we don't recompose when it's not necessary. This CL adds a
small test to ensure that existing elements don't recompose when
starting or finishing a transition.

Bug: 291071158
Flag: NA
Test: ElementTest
Change-Id: Idccc990000d7678261c6a14c7a86aedbc353221d
parent 2205c0aa
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.compose.animation.scene

import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.movableContentOf
import androidx.compose.runtime.mutableStateOf
@@ -47,6 +48,7 @@ import com.android.compose.ui.util.lerp
import kotlinx.coroutines.launch

/** An element on screen, that can be composed in one or more scenes. */
@Stable
internal class Element(val key: ElementKey) {
    /**
     * The last values of this element, coming from any scene. Note that this value will be unstable
@@ -91,6 +93,7 @@ internal class Element(val key: ElementKey) {
    }

    /** The target values of this element in a given scene. */
    @Stable
    class TargetValues(val scene: SceneKey) {
        val lastValues = Values()

@@ -108,6 +111,7 @@ internal class Element(val key: ElementKey) {
    }

    /** A shared value of this element. */
    @Stable
    class SharedValue<T>(val key: ValueKey, initialValue: T) {
        var value by mutableStateOf(initialValue)
    }
+2 −0
Original line number Diff line number Diff line
@@ -17,11 +17,13 @@
package com.android.compose.animation.scene

import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Stable

/**
 * A base class to create unique keys, associated to an [identity] that is used to check the
 * equality of two key instances.
 */
@Stable
sealed class Key(val debugName: String, val identity: Any) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
+10 −5
Original line number Diff line number Diff line
@@ -19,11 +19,13 @@ package com.android.compose.animation.scene
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@@ -34,6 +36,7 @@ import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.zIndex

/** A scene in a [SceneTransitionLayout]. */
@Stable
internal class Scene(
    val key: SceneKey,
    layoutImpl: SceneTransitionLayoutImpl,
@@ -105,12 +108,14 @@ private class SceneScopeImpl(
    ): State<T> {
        val element =
            element?.let { key ->
                Snapshot.withoutReadObservation {
                    layoutImpl.elements[key]
                        ?: error(
                        "Element $key is not composed. Make sure to call animateSharedXAsState " +
                            "*after* Modifier.element(key)."
                            "Element $key is not composed. Make sure to call " +
                                "animateSharedXAsState *after* Modifier.element(key)."
                        )
                }
            }

        return animateSharedValueAsState(
            layoutImpl,
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.compose.animation.scene
import androidx.annotation.FloatRange
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
@@ -95,6 +96,7 @@ interface SceneTransitionLayoutScope {
@DslMarker annotation class ElementDsl

@ElementDsl
@Stable
interface SceneScope {
    /** The state of the [SceneTransitionLayout] in which this scene is contained. */
    val layoutState: SceneTransitionLayoutState
+2 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
@@ -41,6 +42,7 @@ import com.android.compose.ui.util.lerp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel

@Stable
internal class SceneTransitionLayoutImpl(
    onChangeScene: (SceneKey) -> Unit,
    builder: SceneTransitionLayoutScope.() -> Unit,
Loading