Compose Runtime
| Latest Update | Current Release |
|---|---|
| August 5, 2020 | 0.1.0-dev16 |
Declaring dependencies
To add a dependency on Compose, you must add the Google Maven repository to your project. Read Google's Maven repository for more information.
Add the dependencies for the artifacts you need in the build.gradle file for
your app or module:
dependencies {
implementation "androidx.compose.runtime:runtime:0.1.0-dev16"
implementation "androidx.compose.runtime:runtime-livedata:0.1.0-dev16"
implementation "androidx.compose.runtime:runtime-rxjava2:0.1.0-dev16"
}
android {
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerVersion "1.4.0-rc"
kotlinCompilerExtensionVersion "0.1.0-dev16"
}
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs += ["-Xallow-jvm-ir-dependencies", "-Xskip-prerelease-check"]
}
}
For more information about dependencies, see Add build dependencies.
Feedback
Your feedback helps make Jetpack better. Let us know if you discover new issues or have ideas for improving this library. Please take a look at the existing issues in this library before you create a new one. You can add your vote to an existing issue by clicking the star button.
See the Issue Tracker documentation for more information.
Version 0.1.0-dev
Version 0.1.0-dev16
August 5, 2020
androidx.compose.runtime:runtime-*:0.1.0-dev16 is released. Version 0.1.0-dev16 contains these commits.
API Changes
The default mutation policy of
mutableStateOf(),ambientOf()andsavedInstanceStateOf()has changed to bestructuralEqualityPolicy()instead ofreferentialEqualityPolicy().The default for deciding if a new value assigned to a
mutableStateOf()instance is considered a change now defaults to using==instead of using===.See https://kotlinlang.org/docs/reference/equality.html
ambientOf()andsavedInstanceStateOf()usemutableStateOf()in their implementations so they were changed to be consistent withmutableStateOf().Using structural equality more closely matches developer expectations.
For example,
val state = mutableStateOf(1f)followed by,
state.value = 1fwill no longer be consider a change to
stateand uses ofstateduring composition will no longer need to be recomposed.This is a breaking change but, in most cases (such when using classes that do not override
equals()), this will not have a noticeable effect on an application.Classes that do override
equals(), such asdataclasses, might see a performance degradation as theirequals()methods are now, by default, called when assigned to amutableStateOf().The previous behavior can be restored by adding the policy parameter
policy = referentialEqualityPolicy()to calls tomutableStateOf(),ambientOf()andsavedInstanceStateOf(). (Ic21a7)RowandColumnare now inline function significantly reducing the overhead of using them. (I75c10)
Bug Fixes
- setViewContent was deprecated. setContent should be used instead. (I7e497, b/160335130)
Added MonotonicFrameAnimationClock that enables you to use a MonotonicFrameClock as an AnimationClockObservable to bridge the gap between the new coroutines based clocks and APIs that still use the old callback based clocks.
The MonotonicFrameClock equivalent of ManualAnimationClock is now ManualFrameClock. (I111c7, b/161247083)
Modifier.stateDraggable was completely reworked and renamed to Modifier.swipeable. A new SwipeableState class was introduced, and DrawerState and BottomDrawerState were refactored to inherit from it. [Modal/Bottom]DrawerLayout no longer take an onStateChange parameter. (I72332, b/148023068)
Modifier.plus has been deprecated, use Modifier.then instead. 'Then' has a stronger signal of ordering, while also prohibits to type
Modifier.padding().background() + anotherModifier, which breaks the chain and harder to read (Iedd58, b/161529964)SubcomposeLayout is added. It is a low level primitive which allows to compose the children during the measuring if we want to use some values available only later during the measure for the subtree composition. For example WithConstraints is not implemented using SubcomposeLayout. (I25cc8)
Material FilledTextField was renamed to TextField and foundational TextField was renamed to BaseTextField to make simplest desired API easy to discover and use (Ia6242, b/155482676)
Modifier.drawBackground has been renamed to Modifier.background (I13677)
Version 0.1.0-dev15
July 22, 2020
androidx.compose.runtime:runtime-*:0.1.0-dev15 is released. Version 0.1.0-dev15 contains these commits.
Dependencies Update
- To use the
0.1.0-dev15version of Compose, you will need to update your dependencies according to the new code snippets shown above in Declaring dependencies.
API Changes
@Modelannotation is now deprecated. Use state and mutableStateOf as alternatives. This deprecation decision was reached after much careful discussion.Justification
Rationale includes but is not limited to:
- Reduces API surface area and concepts we need to teach
- More closely aligns with other comparable toolkits (Swift UI, React, Flutter)
- Reversible decision. We can always bring
@Modelback later. - Removes corner-case usage and difficult to answer questions about configuring
@Modelas things we need to handle @Modeldata classes, equals, hashcode, etc.- How do I have some properties “observed” and others not?
- How do I specify structural vs. referential equality to be used in observation?
- Reduces “magic” in the system. Would reduce the likelihood of someone assuming system was smarter than it is (ie, it knowing how to diff a list)
- Makes the granularity of observation more intuitive.
- Improves refactorability from variable -> property on class
- Potentially opens up possibilities to do hand-crafted State-specific optimizations
- More closely aligns with the rest of the ecosystem and reduces ambiguity towards immutable or us “embracing mutable state”
Migration Notes
Almost all existing usages of
@Modelare fairly trivially transformed in one of two ways. The example below has a@Modelclass with two properties just for the sake of example, and has it being used in a composable.@Model class Position( var x: Int, var y: Int ) @Composable fun Example() { var p = remember { Position(0, 0) } PositionChanger( position=p, onXChange={ p.x = it } onYChange={ p.y = it } ) }Alternative 1: Use
State<OriginalClass>and create copies.This approach is made easier with Kotlin’s data classes. Essentially, make all previously
varproperties intovalproperties of a data class, and then usestateinstead ofremember, and assign the state value to cloned copies of the original using the data classcopy(...)convenience method.It’s important to note that this approach only works when the only mutations to that class were done in the same scope that the
Stateinstance is created. If the class is internally mutating itself outside of the scope of usage, and you are relying on the observation of that, then the next approach is the one you will want to use.data class Position( val x: Int, val y: Int ) @Composable fun Example() { var p by state { Position(0, 0) } PositionChanger( position=p, onXChange={ p = p.copy(x=it) } onYChange={ p = p.copy(y=it) } ) }Alternative 2: Use mutableStateOf and property delegates
This approach is made easier with Kotlin’s property delegates and the
mutableStateOfAPI which allows you to create MutableState instances outside of composition. Essentially, replace allvarproperties of the original class withvarproperties withmutableStateOfas their property delegate. This has the advantage that the usage of the class will not change at all, only the internal implementation of it. The behavior is not completely identical to the original example though, as each property is now observed/subscribed to individually, so the recompositions you see after this refactor could be more narrow (a good thing).class Position(x: Int, y: Int) { var x by mutableStateOf(x) var y by mutableStateOf(y) } // source of Example is identical to original @Composable fun Example() { var p = remember { Position(0, 0) } PositionChanger( position=p, onXChange={ p.x = it } onYChange={ p.y = it } ) }(I409e8, b/152050010, b/146362815, b/146342522, b/143413369, b/135715219, b/143263925, b/139653744)
Changes the code generation strategy of Compose’s compiler. Prior to the change, the compose compiler would transform calls to composable functions. With this change, we now transform the body of a composable function and leave the callsite unaltered (mostly).
This means that most of the logic communicating with the compose runtime happens at the start of the function body, instead of at the callsite.
This should be a source-compatible change for all usage of compose. Most users of compose should not have to update any code as a result of this change.
In order to support this work, the JVM signature of all composable functions has changed. A Composable function accepting a single parameter is transformed into a function accepting 3 parameters, the additional parameters are the Composer, a ‘key’ integer. a bitmask integer used to propagate metadata through calls.
Compose now also transforms default arguments to a composable function. It does this without introducing an additional synthetic default overload of the function itself, so this change will result in fewer functions being defined.
Known intentional behavioral changes resulting from this:
- Some calls will skip where they wouldn’t have previously
- Composable expressions in default argument expressions are now correctly subscribed to and handled
This work included some optimizations: 1. The result of comparisons of parameters are propagated through the call graph to other composable functions. This will result in fewer comparisons at runtime, reduces the slot table size, as well as more skipping of composable functions that were previously not skipped 2. Paremeters which are determined to be “static” at compile time are no longer compared or stored in the runtime. This reduces the number of comparisons and reduces slot table size. 3. Control flow structure of the body of functions is used to minimize the number of groups that are generated. This reduces slot table size and results in less work for the runtime 4. Unused dispatch and receiver parameters to functions are not included in determining skippability of the function if they are not used inside of the body of the function.
Most breaking changes were for APIs that the compiler targets directly, and typical use of compose will not be affected: 1. Composer::startExpr was removed 2. Composer::endExpr was removed 3. Composer::call was deprecated 4. The non-varargs overloads of
keyhave been removed. Use thevarargversion going forward. 5. The Pivotal annotation was deprecated. Usekeyas a replacement. 6. ScopeUpdateScope::updateScope was changed to expect a Function3 instead of Function1 7. restartableFunction and restartableFunctionN were updated to include additional compile time parameters (I60756, b/143464846)Added sortWith and removeRange to MutableVector (Icccf7)
Added default method implementations for CompositionLifecycleObserver (I24289)
Applier now requires a clear() method for disposing compositions (Ibe697)
Added asMutableList() to MutableVector to allow it to be passed to public API without having to copy the entire list. (I298df)
Added rememberCoroutineScope() to obtain a managed CoroutineScope in composition for launching jobs in response to events. (I0e264)
MutableVector is a new collection that does not implement any of the standard Collection interface. This collection offers speed above other requirements and is intended to only be used in internal implementations. (I8ebd6)
Temporarily removed
StableMutableListandStableMutableMapto avoid an issue in the version of Kotlin compose requires. These interfaces will be reintroduced once compose is updated to a version of Kotlin that doesn't have the issue.SnapshotStateListandSnapshotStateMapare now public but they will be deprecated onceStableMutableListandStableMutableMapare restored. (Ia7769)add top-level withFrameNanos function for animation timing (Ie34c5)
@Untracked annotation has been deprecated. Replace with @ComposableContract(tracked=false) (Id211e)
RestartableFunction and associated APIs have been renamed to ComposableLambda, etc. These APIs were targeted only by the compiler so this should not affect source level compatibility normally. The rename was done primarily to communicate what this class is better when it shows up in stack traces (I7eb25)
@Composable annotation is no longer valid on classes (Ia5f02)
Ambient<T>is now @Stable instead of @Immutable (I0b4bb)Prior to this change, the compose compiler plugin would non-trivially intercept calls to constructors inside of a @Composable function if there was an (I5205a, b/158123804)
The Recompose composable is no longer a useful abstraction. Most recomposition should happen as a result of MutableState assignments. For anything beyond that, it is recommended that you use the
invalidatefunction to trigger a recomposition of the current scope. (Ifc992)Observe is no longer a useful abstraction. If you need to replicate it, its implementation can be replicated by just creating a composable function which executes a composable lambda parameter. For example,
@Composable fun Observe(body: @Composable () -> Unit) = body()(I40d37)@Direct was deprecated in favor of @ComposableContract(restartable=false) (If4708)
Added an adapter for the recently introduced StateFlow which allows as to pre-populate the initial value so the returned State is non-nullable (I61dd8, b/156233789)
Added an adapter for Flow. Example of the usage: val value by flow.collectAsState() (If2198, b/153375923)
[Mutable]State property delegate operators moved to extensions to support Kotlin 1.4 property delegate optimizations. Callers must add imports to continue using
by state { ... }orby mutableStateOf(...). (I5312c)androidx.compose.ViewComposer has been moved to androidx.ui.node.UiComposer androidx.compose.Emittable has been removed. It was redundant with ComponentNode. androidx.compose.ViewAdapters has been removed. They are no longer a supported use case. Compose.composeInto has been deprecated. Use
setContentorsetViewContentinstead. Compose.disposeComposition has been deprecated. Use thedisposemethod on theCompositionreturned bysetContentinstead. androidx.compose.Compose.subcomposeInto has moved to androidx.ui.core.subcomposeInto ComponentNode#emitInsertAt has been renamed to ComponentNode#insertAt ComponentNode#emitRemoveAt has been renamed to ComponentNode#removeAt ComponentNode#emitMode has been renamed to ComponentNode#move (Idef00)Updated the
ComposeFlags.COMPOSER_PARAMflag to betrue, which will change the code generation strategy for the compose plugin. At a high level, this causes @Composable functions to be generated with an additional synthetic parameter, which is passed through to subsequent @Composable calls in order for the runtime to properly manage execution. This is a significant binary breaking change, however, should preserve source-level compatibility in all sanctioned usage of compose. (I7971c)Breaking changes to the ambients API. See log and
Ambient<T>documentation for details (I4c7ee, b/143769776)Added ui-livedata - new artifact with an adapter for LiveData. Example of the usage: val value by liveData.observeAsState() (Ie9e8c, b/150465596)
Rx adapters without explicit initial value are deprecated. Using null is not always the best default, for example when you have a List it is better to start with emptyList() or any other reasonable default (I00025, b/161348384)
Added ui-rxjava2 - new artifact with adapters for RxJava2. Example of the usage: val value by observable.subscribeAsState() (Ifab4b, b/153369097)
savedInstanceState()can now be used with nullable types (I6847f, b/153532190)New listSaver() and mapSaver() to make it easier to write custom Saver objects (I8cf68, b/152331508)
New functions: savedInstanceState() and rememberSavedInstanceState(). They are similar to state() and remember() but have a saved instance state support build in (If1987, b/152025209)
Bug Fixes
runOnIdleComposerenamed torunOnIdle(I83607)- Made LayoutNode experimental API (I4f2e9)
- androidx.ui.foundation.TextFieldValue and androidx.ui.input.EditorValue is deprecated. TextField, FilledTextField and CoreTextField composables that uses that type is also deprecated. Please use androidx.ui.input.TextFieldValue instead (I4066d, b/155211005)
- Removed deprecated DrawBackground API in favor of drawBackground extension APIs on Modifier. Refactored color, brush and paint drawBackground implementations to reduce code paths as well as remove requirement for Modifier to be created as part of composition. (I0343a)
- Updated higher level compose APIs that expose a Canvas to expose CanvasScope instead. This removes the need for consumers to maintain their own Paint objects. For consumers that still require access to a Canvas they can use the drawCanvas extension method which provides a callback to issue drawing commands with the underlying Canvas. (I80afd)
- WithConstraints trailing lambda API has been changed. Now instead of two params it has a receiver scope which in addition to constraints and layoutDirection provides minWidth, maxWidth, minHeight and maxHeight properties in Dp (I91b9a, b/149979702)
- Added symmetric padding modifier. (I39840)
- Updated wrapContentWidth and wrapContentHeight to expect vertical or horizontal Alignment rather than any Alignment. The gravity modifier was updated to accept vertical or horizontal Alignment. Row, Column and Stack were updated to support custom continuous Alignments. (Ib0728)
- ui-text module is renamed as ui-text-core (I57dec)
- Improve DrawModifier API:
- Made the receiver scope for draw() ContentDrawScope
- Removed all parameters on draw()
- DrawScope has same interface as former CanvasScope
- ContentDrawScope has drawContent() method (Ibaced, b/152919067)
- ColoredRect has been deprecated. Use
Box(Modifier.preferredSize(width, height).drawBackground(color))instead. (I499fa, b/152753731) - Replaced Modifier plus operator with factory extension functions (I225e4)
- RowScope and ColumnScope members are now accessible outside Row and Column. (I3a641)
- Renamed LayoutFlexible to LayoutWeight. Renamed tight parameter to fill. (If4738)
- WithConstraints got LayoutDirection parameter (I6d6f7)
- Renamed background to DrawBackground and make it to be memorized by default (Ia0bd3)
- Replaced ButtonStyle with distinct functions and removed text (string) overload. See updated samples for usage information. (If63ab, b/146478620, b/146482131)
runOnIdleComposeandrunOnUiThreadare now global functions instead of methods on ComposeTestRule. (Icbe8f)
External Contribution
- Remove unneeded API such as Looper and Handler from Compose Runtime porting layer (I6847d)
- Deprecate
Flow<T>.collectAsState()with no initial value. UseStateFlow<T>or pass an explicit initial value instead. (I63f98, b/157674865)

