Google 致力于为黑人社区推动种族平等。查看具体举措

Compose 运行时

Compose 的编程模型和状态管理的基本构建块,以及 Compose 编译器插件针对的核心运行时。
最近更新时间 当前稳定版 下一候选版本 Beta 版 Alpha 版
2020 年 9 月 2 日 - - - 1.0.0-alpha02

结构

Compose 由 androidx 中的 7 个 Maven 组 ID 构成。每个组都包含部分指定功能,每个功能都有各自的一组版本说明。

下表介绍了各个组及指向每组版本说明的链接。

说明
compose使用描述界面形状和数据依赖项的可组合函数,以编程方式定义界面。
compose.animation在 Jetpack Compose 应用中构建动画,丰富用户的体验。
compose.foundation使用现成可用的构建块编写 Jetpack Compose 应用,还可扩展 Foundation 以构建您自己的设计系统元素。
compose.material使用现成可用的 Material Design 组件构建 Jetpack Compose UI。这是 Compose 的更高级别的入口点,旨在提供与 www.material.io 上描述的组件一致的组件。
compose.runtimeCompose 的编程模型和状态管理的基本构建块,以及 Compose 编译器插件针对的核心运行时。
compose.ui与设备互动所需的 Compose UI 的基本组件,包括布局、绘图和输入。
ui使用 Jetpack Compose 库。

声明依赖项

如需添加 Compose 的依赖项,您必须将 Google Maven 代码库添加到项目中。如需了解详情,请参阅 Google 的 Maven 代码库

在应用或模块的 build.gradle 文件中添加所需工件的依赖项:

dependencies {
    implementation "androidx.compose.runtime:runtime:1.0.0-alpha02"
    implementation "androidx.compose.runtime:runtime-livedata:1.0.0-alpha02"
    implementation "androidx.compose.runtime:runtime-rxjava2:1.0.0-alpha02"
}

android {
    buildFeatures {
        compose true
    }

    composeOptions {
        kotlinCompilerVersion "1.4.0"
        kotlinCompilerExtensionVersion "1.0.0-alpha02"
    }
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
    kotlinOptions {
        jvmTarget = "1.8"
        freeCompilerArgs += ["-Xallow-jvm-ir-dependencies", "-Xskip-prerelease-check"]
    }
}

如需详细了解依赖项,请参阅添加构建依赖项

反馈

您的反馈将帮助我们改进 Jetpack。如果您发现了新问题,或对库的改进有某些建议,请告诉我们。创建新问题前,请先查看此库中的现有问题。您可以点击“加注星标”按钮,为现有问题投票。

创建新问题

如需了解详情,请参阅问题跟踪器文档

版本 1.0.0

版本 1.0.0-alpha02

2020 年 9 月 2 日

发布了 androidx.compose.runtime:runtime-*:1.0.0-alpha02版本 1.0.0-alpha02 中包含这些提交内容

API 变更

  • 添加了 snapshotFlowwithMutableSnapshot API,分别用于使用和生成快照数据更改。(I3e722)
  • 可组合函数的调用规范发生了变化。这是一项重大的二进制文件更改。所有库都必须重新编译才能使用此版本的 Compose 编译器插件。

    这项更改不会在源代码级别产生重大变化,因为只有已更改的 API 属于明确选择启用的编译器 API。(I7afd2b/158123185

  • 从 EmbeddingContext 中移除了调度方法 (I7b9be)

  • 弃用了 onPreCommit;onCommit 的功用现在与 onPreCommit 相同。

    现在,onCommit 和 onActive 在提交组成部分变更的同一 Choreographer 帧中运行,而不是在下一个 Choreographer 帧开始处运行。(I70403)

版本 1.0.0-alpha01

2020 年 8 月 26 日

发布了 androidx.compose.runtime:runtime-*:1.0.0-alpha01版本 1.0.0-alpha01 中包含这些提交内容

版本 0.1.0-dev

版本 0.1.0-dev17

2020 年 8 月 19 日

发布了 androidx.compose.runtime:runtime-*:0.1.0-dev17版本 0.1.0-dev17 中包含这些提交内容

API 变更

  • 自定义 emit 现在可以做如下声明:可以跳过它的一个或多个 setter,并且可以独立于 emit 对 setter 进行重新组合。(Ibbd13)
  • 移除了已弃用的 FrameManager 调用。

    更改了内部 Compose API,从而降低了跟踪状态对象(如 mutableStateof())所需的开销 (I80ba6)

  • 为清楚起见,现在弃用了 state { ... } 可组合项,改为对 remember { mutableStateOf(...) } 的显式调用。这样可减少管理状态所需的整体 API Surface 及概念数量,且与类属性委托的 by mutableStateOf() 模式相一致。(Ia5727)

  • Flow.collectAsState 现在根据组合本身来确定默认调度程序,而非默认使用 Dispatchers.Main。(I9c1d9)

  • 解决了在 for 循环内使用某些用于保存状态的方法时出现崩溃的问题。现已支持在 savedInstanceState() 中使用同一键,并已根据此新要求对 UiSavedStateRegistry 的 API 做出调整(I4ab76b/160042650b/156853976b/159026663b/154920561

问题修复

  • 已弃用 emitView。请在可行的情况下改用 AndroidView 在 Compose 中发出 View。请注意,今后将不再支持直接对 View 和 ViewGroup 进行组合,除非二者是组合树的分支(在这种情况下,可通过 AndroidView 进行组合)。(I29b1eb/163871221

版本 0.1.0-dev16

2020 年 8 月 5 日

发布了 androidx.compose.runtime:runtime-*:0.1.0-dev16版本 0.1.0-dev16 中包含这些提交内容

API 变更

  • mutableStateOf()ambientOf()savedInstanceStateOf() 的默认突变政策已更改为 structuralEqualityPolicy()(而非 referentialEqualityPolicy())。

    现在默认使用使用 ==(而非 ===)来确定是否将新值分配给 mutableStateOf() 实例。

    请参阅 https://kotlinlang.org/docs/reference/equality.html

    ambientOf()savedInstanceStateOf() 在其实现中使用 mutableStateOf(),因此,已对二者进行更改以与 mutableStateOf() 保持一致。

    结构相等的使用现在更符合开发者的预期。

    例如,

    val state = mutableStateOf(1f)
    

    后跟

    state.value = 1f
    

    不再被视为对 state 的更改,且在组合过程中使用 state 时不再需要重新组合。

    这是一项重大变更,但在大多数情况下(例如,使用不会替换 equals() 的类时)不会对应用产生明显影响。

    会替换 equals() 的类(例如 data 类)可能会出现性能下降,因为现在系统默认会在将其 equals() 方法分配给 mutableStateOf() 时调用这些方法。

    如需恢复之前的行为,请在对 mutableStateOf()ambientOf()savedInstanceStateOf() 的调用中添加政策参数 policy = referentialEqualityPolicy()。(Ic21a7)

  • RowColumn 现在属于内联函数,其使用开销将显著降低。(I75c10)

问题修复

  • 已弃用 setViewContent,请改用 setContent。(I7e497b/160335130
  • 添加了 MonotonicFrameAnimationClock,您可将 MonotonicFrameClock 用作 AnimationClockObservable,以消除基于协程的新时钟与仍使用基于旧回调的时钟的 API 之间的差异。

    现在,ManualAnimationClock 的 MonotonicFrameClock 等效项是 ManualFrameClock。(I111c7b/161247083

  • 我们对 Modifier.stateDraggable 进行了彻底的重新设计,并将其重命名为 Modifier.swipeable。引入了一个新 SwipeableState 类,并对 DrawerState 和 BottomDrawerState 进行了重构,使其可从该类继承数据。[Modal/Bottom]DrawerLayout 不再使用 onStateChange 参数。(I72332b/148023068

  • 已弃用 Modifier.plus,现在改用 Modifier.then。“Then”能够更明确地指出先后执行顺序,同时还禁止输入会破坏链且降低可读性的 Modifier.padding().background() + anotherModifierIedd58b/161529964

  • 添加了 SubcomposeLayout。这是一个低级别基元,如果我们想要使用仅在衡量子树组合期间后期可用的一些值,就可以利用此基元在衡量期间组合子项。例如,WithConstraints 就并非通过 SubcomposeLayout 实现。(I25cc8)

  • Material FilledTextField 已重命名为 TextField,且基础 TextField 已重命名为 BaseTextField,您可轻松寻找并使用所需的最简单的 API(Ia6242b/155482676

  • Modifier.drawBackground 已重命名为 Modifier.background (I13677)

版本 0.1.0-dev15

2020 年 7 月 22 日

发布了 androidx.compose.runtime:runtime-*:0.1.0-dev15版本 0.1.0-dev15 中包含这些提交内容

依赖项更新

  • 如需使用 Compose 的 0.1.0-dev15 版本,您需要根据上面声明依赖项部分给出的新代码段来更新依赖项。

API 变更

  • @Model 注释现已弃用。请使用 state 和 mutableStateOf 作为替代方案。经仔细讨论之后,我们做出了这一弃用决定。

    理由

    理由包括但不限于:

    • 减少 API Surface 区域和我们需要传授的概念
    • 更为贴近其他类似工具包(Swift UI、React、Flutter)
    • 这是一项可撤消的决定。我们以后可以随时恢复 @Model
    • 解决了极端情况下的使用难题,轻松回答了有关将 @Model 配置为我们需要处理的内容的问题
    • @Model 数据类、等号、哈希代码等。
    • 如何让部分属性“被观测”,而其他属性不被观测?
    • 如何指定要在观测中使用的结构性与指示性等式?
    • 减少系统中的“魔力”。这会降低有人误认为系统比实际上要更智能(即知道如何区分列表)的可能性
    • 使观测的粒度更为直观。
    • 改进了类中从变量到属性的可重构性
    • 可能使您可以手动进行针对特定状态的优化
    • 与生态系统的其他部分更加贴近,并减少了在不可变性或我们“接受可变状态”方面的不确定性

    迁移注意事项

    @Model 的几乎所有现有用例都可通过两种方式进行转换。以下示例具有一个 @Model 类,该类有两个属性(仅作示例),用在一个组合项中。

    @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 }
     )
    }
    

    替代方案 1:使用 State<OriginalClass> 并创建副本。

    使用 Kotlin 的数据类可以更轻松地实现此方法。从本质上讲,请将之前的所有 var 属性设为数据类的 val 属性,然后使用 state 而不是 remember,并将状态值分配给使用数据类 copy(...) 便捷方法的原始版本的克隆副本。

    请注意,只有当该类的唯一转变发生在创建 State 实例的同一范围内时,此方法才有效。如果类在使用范围之外发生内部变化,并且您依赖于对该范围的观察,则您需要使用下一种方法。

    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) }
     )
    }
    

    替代方案 2:使用 mutableStateOf 和属性委托

    使用 Kotlin 的属性委托和 mutableStateOf API 可以更轻松地实现此方法,使您可以在组合之外创建 MutableState 实例。实际上,请将原始类的所有 var 属性替换为以 mutableStateOf 作为属性委托的 var 属性。这样做的好处是,类的使用情况完全不会改变,变化的只是其内部实现。不过,这种行为与原始示例并不完全相同,因为每个属性现在都是单独观察/订阅的,因此您在重构后看到的重新组合可能会变窄(这是好事)。

    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 }
     )
    }
    

    I409e8b/152050010b/146362815b/146342522b/143413369b/135715219b/143263925b/139653744

  • 更改了 Compose 的编译器的代码生成策略。在更改之前,Compose 编译器会转换对可组合函数的调用。进行此更改后,现在我们可以转换可组合函数的正文,并使调用位置保持不变(大多数情况下)。

    这意味着与 Compose 运行时进行通信的大多数逻辑发生在函数正文的开头,而不是在调用位置。

    这应该是针对所有 Compose 操作的源兼容性更改。大多数 Compose 用户都不需要在更改后更新任何代码。

    为了支持这项更改,所有可组合函数的 JVM 签名均已更改。将接受单个参数的可组合函数转换为接受 3 个参数的函数,其他参数为合成器,即“键”整数,一个用于通过调用传播元数据的位掩码整数。

    Compose 现在还会将默认参数转换为可组合函数。这项操作不会引入函数本身的额外合成默认过载,因此此更改会导致定义的函数变少。

    已知的有意行为更改是由于以下原因造成的:

    1. 有些调用会跳过之前不会跳过的位置
    2. 默认参数表达式中的可组合项表达式现已正确订阅并处理

    这项工作包括一些优化: 1. 参数的比较结果通过调用图传播到其他可组合项函数。这将导致运行时比较数减少,槽表大小减小,并更多地跳过之前不跳过的可组合项函数 2. 在编译时被确定为“静态”的参数将不再进行比较或存储在运行时中。这样可以减少比较数并减小槽表大小。 3. 函数正文的控制流结构用于最大限度减少生成的组数量。这样可以减小槽表大小,并减少运行时工作量 4. 如果未在函数正文内部使用调度和接收器参数,则在确定函数的可跳过性时不包含未使用的这些参数。

    大多数破坏性更改都面向编译器直接针对的 API,并且通常不会影响 Compose: 1. 移除了 Composer::startExpr 2. 移除了 Composer::endExpr 3. 弃用了 Composer::call 4. 移除了 key 的非可变参数过载。今后将使用 vararg 版本。 5. 弃用了 Pivotal 注释。使用 key 作为替代方案。6. ScopeUpdateScope::updateScope 已更改为函数 3 而非函数 1 7. 更新了 restartableFunction 和 restartableFunctionN,以包含其他编译时参数(I60756b/143464846

  • 向 MutableVector 添加了 sortWith 和 removeRange (Icccf7)

  • 为 CompositionLifecycleObserver 添加了默认方法实现 (I24289)

  • Applier 现在需要一种 clear() 方法来处理组合 (Ibe697)

  • 向 MutableVector 添加了 asMutableList(),以使其能够传递到公共 API,而不必复制整个列表。(I298df)

  • 添加了 rememberCoroutineScope() 以获取组合中托管的 CoroutineScope,以便启动任务来响应事件。(I0e264)

  • MutableVector 是一个新的集合,不实现任何标准 Collection 接口。此集合提供了高于其他要求的速度,并且仅适用于内部实现。(I8ebd6)

  • 暂时移除了 StableMutableListStableMutableMap,以避免 Compose 所需的 Kotlin 版本出现问题。一旦 Compose 更新到不存在问题的 Kotlin 版本,就会重新引入这些接口。

    SnapshotStateListSnapshotStateMap 现已公开,但恢复 StableMutableListStableMutableMap 后就会将其弃用。(Ia7769)

  • 添加了顶级 onFrameNanos 函数用于动画定时 (Ie34c5)

  • 已弃用 @Untracked 注释,替换为 @ComposableContract(tracked=false) (Id211e)

  • RestartableFunction 和关联的 API 已重命名为 ComposableLambda 等。因为只有编译器针对这些 API,所以此变更在正常情况下应该不会影响源代码级别的兼容性。重命名的主要目的是,当这个类出现在堆栈轨迹中时,用户能够更清晰地了解这个类 (I7eb25)

  • @Composable 注释在类上不再有效 (Ia5f02)

  • Ambient<T> 现在带有 @Stable 注释而不是 @Immutable 注释 (I0b4bb)

  • 在此变更之前,如果存在 @Composable 函数,Compose 编译器插件会以非常复杂的方式拦截对该函数内构造函数的调用(I5205ab/158123804

  • Recompose 可组合项已不再属于有效抽象。大多数重新组合都应由 MutableState 分配促成。在此之外,建议您使用 invalidate 函数来触发对当前范围的重新组合。(Ifc992)

  • Observe 已不再属于有效抽象函数。如需对其进行复制,只需创建一个执行可组合 lambda 参数的可组合函数即可复制其实现。例如,@Composable fun Observe(body: @Composable () -> Unit) = body() (I40d37)

  • 弃用了 @Direct,取而代之的是 @ComposableContract(restartable=false) (If4708)

  • 为最近引入的 StateFlow 添加了一个适配器,可用于预填充初始值,使返回的 State 不可为 null(I61dd8b/156233789

  • 为 Flow 添加了一个适配器。用法示例:val value by flow.collectAsState()(If2198b/153375923

  • [Mutable]State 属性委托运算符移到了扩展程序,以支持 Kotlin 1.4 属性委托优化。调用方必须添加 import 才能继续使用 by state { ... }by mutableStateOf(...)。(I5312c)

  • androidx.compose.ViewComposer 移到了 androidx.ui.node.UiComposer。移除了 androidx.compose.Emittable,它与 ComponentNode 重复。移除了 androidx.compose.ViewAdapters,它们不再是受支持的用例。已弃用 Compose.composeInto,改为使用 setContentsetViewContent。已弃用 Compose.disposeComposition,改用 setContent 返回的 Compositiondispose 方法。androidx.compose.Compose.subcomposeInto 已移到 androidx.ui.core.subcomposeInto。ComponentNode#emitInsertAt 已重命名为 ComponentNode#insertAt。ComponentNode#emitRemoveAt 已重命名为 ComponentNode#removeAt。ComponentNode#emitMode 已重命名为 ComponentNode#move (Idef00)

  • 已将 ComposeFlags.COMPOSER_PARAM 标记更新为 true,这将改变 Compose 插件的代码生成策略。大体而言,这会导致 @Composable 函数通过其他合成参数生成,该参数会传递到后续 @Composable 调用,以便运行时正确管理执行。这是一项重大的二进制文件更改,但应当在所有获得许可的 Compose 使用情况中保留源代码级别的兼容性。(I7971c)

  • Ambient API 重大更改。如需了解详情,请参阅日志和 Ambient<T> 文档(I4c7eeb/143769776

  • 添加了 ui-livedata - 带适用于 LiveData 的适配器的新工件。用法示例:val value by liveData.observeAsState()(Ie9e8cb/150465596

  • 已弃用没有明确的初始值的 Rx 适配器。使用 null 作为默认值并不一定是最佳选择,以 List 为例,最好是以 emptyList() 开头(I00025b/161348384

  • 添加了 ui-rxjava2 - 带适用于 RxJava2 的适配器的新工件。用法示例:val value by observable.subscribeAsState()(Ifab4bb/153369097

  • savedInstanceState() 现在可以与可为 null 的类型一起使用(I6847fb/153532190

  • 新增了 listSaver() 和 mapSaver(),可让您更轻松地编写自定义 Saver 对象(I8cf68b/152331508

  • 新函数:savedInstanceState() 和 rememberSavedInstanceState()。它们与 state() 和 remember() 类似,但包含已保存实例状态支持构建(If1987b/152025209

问题修复

  • runOnIdleCompose 已重命名为 runOnIdle (I83607)
  • 将 LayoutNode 变成了实验性 API (I4f2e9)
  • 弃用了 androidx.ui.foundation.TextFieldValue 和 androidx.ui.input.EditorValue。还弃用了使用该类型的 TextField、FilledTextField 和 CoreTextField 可组合项。请改为使用 androidx.ui.input.TextFieldValue(I4066db/155211005
  • 移除了已弃用的 DrawBackground API,改为在修饰符上使用 drawBackground 扩展 API。重构了颜色、笔刷和涂料 drawBackground 实现,以减少代码路径,并且不再要求在组合过程中创建修饰符。(I0343a)
  • 更新了公开画布的更高级别的 Compose API,改为公开 CanvasScope。这样一来,用户便无需再维护自己的渲染对象。对于仍需要访问画布的使用方,可以使用 drawCanvas 扩展程序方法,该方法提供回调以向底层画布发出绘制命令。(I80afd)
  • withConstraints 尾随 lambda API 已更改。现在,除了两个参数之外,它还具有接收器范围,除了约束和 LayoutDirection 之外,还可以在 Dp 中提供 minWidth、maxWidth、minHeight 和 maxHeight 属性(I91b9ab/149979702
  • 新增了对称内边距修饰符。(I39840)
  • 更新了 wrapContentWidth 和 wrapContentHeight,预计会显示垂直或水平 Alignment,而不是任意 Alignment。Gravity 修饰符已更新为接受垂直或水平 Alignment。更新了 Row、Column 和 Stack,以支持自定义的连续 Alignment。(Ib0728)
  • ui-text 模块已重命名为 ui-text-core (I57dec)
  • 改进了 DrawModifier API:
    • 确定了 draw() ContentDrawScope 的接收器范围
    • 移除了 draw() 上的所有参数
    • DrawScope 的接口与之前的 CanvasScope 接口相同
    • ContentDrawScope 具有 drawContent() 方法(Ibacedb/152919067
  • 已弃用 ColoredRect,现改用 Box(Modifier.preferredSize(width, height).drawBackground(color))。(I499fab/152753731
  • 将修饰符以及运算符替换成了出厂扩展函数 (I225e4)
  • 现在可以在 Row 和 Column 之外访问 RowScope 和 ColumnScope 成员。(I3a641)
  • LayoutFlexible 已重命名为 LayoutWeight。“tight”参数已重命名为“fill”。(If4738)
  • WithConstraints 获取了 LayoutDirection 参数 (I6d6f7)
  • 已将 background 重命名为 DrawBackground 并设置为默认记住 (Ia0bd3)
  • 将 ButtonStyle 替换成了不同的函数,并移除了文本(字符串)过载。如需了解使用信息,请参阅更新后的示例。(If63abb/146478620b/146482131
  • runOnIdleComposerunOnUiThread 现在是全局函数,而不是 ComposeTestRule 上的方法。(Icbe8f)

外部贡献

  • 从 Compose 运行时移植层移除了 Looper 和 Handler 等不需要的 API (I6847d)
  • 弃用了没有初始值的 Flow<T>.collectAsState(),改为使用 StateFlow<T> 或传递明确的初始值。(I63f98b/157674865