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

Compose 运行时

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

结构

Compose 由 androidx 中的 6 个 Maven 组 ID 构成。每个组都包含一套特定用途的功能,并各有专属的版本说明。

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

说明
compose.animation在 Jetpack Compose 应用中构建动画,丰富用户的体验。
compose.compiler借助 Kotlin 编译器插件,转换 @Composable functions(可组合函数)并启用优化功能。
compose.foundation使用现成可用的构建块编写 Jetpack Compose 应用,还可扩展 Foundation 以构建您自己的设计系统元素。
compose.material使用现成可用的 Material Design 组件构建 Jetpack Compose UI。这是更高层级的 Compose 入口点,旨在提供与 www.material.io 上描述的组件一致的组件。
compose.runtimeCompose 的编程模型和状态管理的基本构建块,以及 Compose 编译器插件针对的核心运行时。
compose.ui与设备互动所需的 Compose UI 的基本组件,包括布局、绘图和输入。

声明依赖项

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

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

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

android {
    buildFeatures {
        compose true
    }

    composeOptions {
        kotlinCompilerVersion "1.4.30"
        kotlinCompilerExtensionVersion "1.0.0-alpha12"
    }
}

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

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

反馈

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

创建新问题

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

版本 1.0.0

版本 1.0.0-alpha12

2021 年 2 月 10 日

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

API 变更

  • 从 UiApplier 移除了对 ViewGroup 的支持。移除了弃用的 emitView 可组合项。(Ifb214)
  • CompositionReference 已重命名为 CompositionContext (I53fcb)
  • ComponentActivity.setContent 已移至 androidx.activity:activity-compose 模块中的 androidx.activity.compose.setContent。(Icf416)
  • 更新了 Snapshot API 以使其更加符合 API 指南,并在公共 API 中隐藏了内部实现类。(Id9e32)
  • 已重命名 Ambient,以与 Ambient 重命名为 CompositionLocal 匹配。Ambient 过去被命名为 AmbientFoo,现在 CompositionLocal 被命名为 LocalFoo。(I2d55d)
  • 将 Ambient 重命名为 CompositionLocal,并分别将 ambientOf / staticAmbientOf 重命名为 compositionLocalOf / staticCompositionLocalOf。这一变更有助于使 CompostionLocal 的目的更加明确:一种用于提供/检索组合本地值的机制。CompositionLocal 实例应带有前缀 Local,例如 val LocalFoo = compositionLocalOf { Foo() }。(Ia55b6)
  • takeMutableSnapshot 和 takeSnapshot 已移至 Snapshot 的配套方法。(I91f19)
  • 已弃用 @ComposableContract,改为使用三个更具体的注解。

    @ComposableContract(restartable = false) 已变为 @NonRestartableComposable@ComposableContract(readonly = true) 已变为 @ReadOnlyComposable@ComposableContract(preventCapture = true) 已变为 @DisallowComposableCalls@ComposableContract(tracked = true) 已被移除。(I60a9d)

  • 已弃用 emptyContent() 和 (@Composable () -> Unit).orEmpty(),因为它们不再具有任何积极的性能影响或价值 (I0484d)

  • snapshotFlowwithMutableSnapshot 不再是实验性方法 (I6a45f)

  • 现在可以关闭 Recomposer。关闭的 Recomposer 会继续重组,直至组合子协程完成。Recomposer.shutdown 已重命名为 cancel,与 close 形成对比。(Ib6d76)

  • compose:runtime-dispatch 工件现已弃用。现在,MonotonicFrameClock 位于 compose:runtime 中,AndroidUiDispatcher 位于 compose:ui 中。(Ib5c36)

  • 已重构 Compose 编译器插件面向的 API,旨在使用接口而不是具体类。接口也不再使用类型参数。

    这种内部更改不会影响源代码兼容性,但这是一项重大的二进制文件更改。(I3b922b/169406779

  • 引入了 SnapshotMutableState (Icfd03)

  • DisposableEffectDisposable 已重命名为 DisposaleEffectResult (Ica7c6)

  • 移除了 Recomposer.current()。[Abstract]ComposeView 现在默认设置为延迟创建的、作用域为窗口的 Recomposer(由窗口的 ViewTreeLifecycleOwner 驱动)。在主机生命周期结束时,系统会暂停重组和基于 withFrameNanos 的动画 tick 操作。(I38e11)

  • Recomposer.runningRecomposers 现在提供只读 RecomposerInfo 的一个全局 StateFlow,用于观察进程中正在进行的合成状态。首选此 API 而不是 Recomposer.current(),后者现在已弃用。(If8ebe)

  • DisposableEffectDisposable 已重命名为 DisposaleEffectResult (I3ea68)

版本 1.0.0-alpha11

2021 年 1 月 28 日

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

API 变更

  • onCommit、onDispose 和 onActive 已弃用,取而代之的是 SideEffect API 和 DisposableEffect API (If760e)
  • emit() API 以及所有重载已弃用,已重命名为 ComposeNode。这些 API 是一样的,只不过为了遵循 Compose 的命名惯例而采用不同的名称 (I4137b)
  • invalidate 和 compositionReference() 现已弃用,取而代之的分别是 currentRecomposeScope 和 rememberCompositionReference。(I583a8)
  • CompositionLifecycleObserver 现已弃用,取而代之的是 RememberObserver。

    RememberObserver 已替代 CompositionLifecycleObserver,且语义和方法名称也已改变。始终推荐的做法是,对那些只记住一次的对象,可以机械地更改为新的 API。不过,如果引用在组合中被记住不止一次,那么对于只调用 onRemembered 一次的每个引用,都会调用 onEnter。如果将 onEnter 用于 WithConstraintsScaffold 等子组合,则会多次调用该对象,从而打破单次调用 onEnter 的保证,而对于 RememberObserver 已将该对象移除。

    RememberObserver 添加了在以下情况下会被调用的 onAbandoned:如果从传递到 remember 的回调中返回 RememberObserver 实例,但该实例在组合状态下不被记住,并因此永远不会调用 onRemembered。当异常导致组合在完成前终止,或者组合因以下两种原因而遭到舍弃时就会发生上述情况:组合因不再是最新的而处于正在生成状态或者组合不再被需要。如果遵循上述单一引用建议的 RememberObserver 实例跟踪的是外部资源,那么 onForgottenonAbandoned 都会表示不再需要该资源。如果该对象跟踪的是 onRemembered 中已开始的工作或已分配的资源,则可以忽略 onAbandoned,因为如果调用 onRemembered,就不会调用 onAbandoned。(I02c36)

  • 不将 collectAsState() 函数标记为内嵌函数 (Ia73e4)

问题修复

  • 已将 WithConstraints 重新设计为 BoxWithConstraints 并移至 foundation.layout。(I9420bb/173387208
  • 在测试中使用 TestCoroutineDispatcher (I532b6)

版本 1.0.0-alpha10

2021 年 1 月 13 日

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

重大变更

  • 重构内部编译器 API 时,允许在所有 @Composable 函数均已完成后,对因为进入“应用更改”组合阶段而生成的节点进行批量更改。

    这是一项可能会影响应用代码的重大行为变更,因为在应用完更改之前,无法再通过内部 API 和实验性 API 提供节点。通常可如下解决此问题:将具有此类依赖项的代码封装在 SideEffect 可组合项中,从而将代码的执行推迟到节点创建和初始化之后。(I018da)

API 变更

  • 添加了在 Recomposer 已应用更改的情况下进行跟踪的方式。(I1b3e2)
  • 扩展了 [Abstract]ComposeView API 以允许回收基于 Compose 的视图,处理其组合以便日后重新创建。添加了用于安装和发现作用域为窗口的 Recomposer 的 API 和用于创建子组合的 CompositionReference。

    添加了 ViewCompositionStrategy,用于配置 [Abstract]ComposeView 的组合处理策略;默认行为是在窗口分离时进行处理。(I860ab)

问题修复

  • Recomposer 现在提供其当前状态的 Flow,因此可监控其 Activity 和相关效果的 Activity。(Ifb2b9)
  • 现在可通过 keyEvent.nativeKeyEvent 访问原生 keyEvent(I87c57b/173086397

版本 1.0.0-alpha09

2020 年 12 月 16 日

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

API 变更

  • 从公共 API 中移除了 SlotTable、SlotReader 和 SlotWriter。这些 API 以前被标记为 InternalComposeAPI,现已变成 Compose 模块的内部 API。

    添加了 CompositionData 和 CompositionGroup,用于替代 ui-tooling API 来提取组合信息。CompositionData 和 CompositionGroup 是公开的,但不能在 ui-tooling API 之外使用,因为它们会提供 ui-tooling API 解译的原生信息 (I31a9c)

  • 不再将 Applier 类视为实验性 API (Id85b0)

  • 更改了 Applier 接口,简化了将树的构建方式从自上而下改为自下而上的过程。

    insert() 方法已重命名为 insertTopDown()

    添加了新方法 insertBottomUp()

    Applier 可以使用 insertTopDown()insertBottomUp() 向正修改的树中插入节点,具体取决于哪个方法的效果更好。

    在构建某些树(例如 LayoutNodeView)时,自下而上构建会比自上而下构建效率更高。在做出此变更之前,若想实现自下而上构建,要进行很多插入操作,并需将插入内容复制到需借助自下而上的构建方式来提高性能的每个 Applier。通过此变更,Applier 替换 insertBottomUp() 即可实现自下而上构建树,替换 insertTopDown() 即可实现自上而下构建树。(Icbdc2)

  • Compose 支持可进行可组合调用的属性 getter。系统不会停止支持此类 getter,但将某个属性 getter 声明为 @Composable 的语法会不断变化。

    要采用现已弃用的语法进行此声明,需对属性本身进行注解:

        @Composable val someProperty: Int get() = ...
    

    要采用目前正确的语法进行此声明,需对属性的 getter 进行注解:

       val someProperty: Int @Composable get() = ...
    

    在一段时间内,这两种语法都能使用,但前者(即现已弃用的语法)最终将导致编译错误。(Id9197)

问题修复

  • 将 AndroidOwner 变为内部函数(Ibcad0b/170296980
  • 将 subcomposeInto(LayoutNode) 变为了内部函数 (Id724a)

版本 1.0.0-alpha08

2020 年 12 月 2 日

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

API 变更

  • 增加了针对可组合 lambda 参数命名和位置的 lint 检查,旨在检查其命名和位置是否符合 Compose 准则。此外,根据 lint 检查结果和指南,还将一些尾随 lambda 名为 children 的 API 迁移到了 content。(Iec48e)
  • Recomposer 不再接受 EmbeddingContext;系统会从 effectCoroutineContext 中获取所需的调度依赖项。弃用了 FrameManager;平台在进行集成时应初始化其自己的全局快照处理操作。(I02369)
  • RestorableStateHolder.withRestorableState 函数已重命名为 RestorableStateProvider (I66640)

问题修复

  • 弃用了名称后缀为 Ambient 的 Ambient 属性,将它们替换成了以 Ambient 为前缀的新属性(以与其他 Ambient 属性保持一致并遵循 Compose API 准则)。(I33440)
  • 移除了旧的 ui-test 模块及其桩 (I3a7cb)

版本 1.0.0-alpha07

2020 年 11 月 11 日

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

新功能

API 变更

  • 弃用了 @UnionType 注解 (I57cde)
  • 添加了 provideDefault,用作提供上下文环境的替代方案,可用于指定只会在尚未提供上下文环境值时设置的上下文环境值。(Id6635b/171024925
  • LaunchedTask 已重命名为 LaunchedEffect,以与 SideEffect 和 DisposableEffect API 保持一致。为了鼓励采用最佳做法,不允许使用不含主题参数的 LaunchedEffect。(Ifd3d4)
  • Applier 现在包含 onBeginChanges/onEndChanges 回调,可在 Composer 开始/结束将更改应用到树时调用。您可根据需要将这些回调用于资源的批量管理。(Icf476)
  • 现在,Recomposer 在构造时需要使用 CoroutineContext (Ic4610)
  • 对不应影响公共 API 的内部 SlotTable 实现进行了更改。(If9828)
  • 移除了不使用初始值的已弃用 rxjava2 适配器 (Idb72f)

问题修复

  • 弃用了 foundation.Text,取而代之的是 material.Text。如需了解不使用来自主题的值的“非预设立场型”基本文本 API,请参阅 androidx.compose.foundation.BasicText。(If64cb)
  • 弃用了 BaseTextField,请改用 BasicTextField。(I896eb)
  • 已将几个与布局相关的符号从 androidx.compose.ui 移至 androidx.compose.layout.ui。(I0fa98b/170475424

外部贡献

  • 添加了用于 Compose 的 runtime-rxjava3 模块。类似于 runtime-rxjava2 (I02cbf)

版本 1.0.0-alpha06

2020 年 10 月 28 日

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

API 变更

  • Recomposer 现在既是一个 CompositionReference,又是一个有效的组合父项。现在,需要使用显式 Recomposer 的情况比以前少。(I4036f)
  • 添加了与 SideEffect 对应的 DisposableEffect API,用于填充 onCommit-with-params 角色,但需要一个必需的 onDispose。
    • 添加了 rememberUpdatedState API,以将数据从重组发布到持续进行或长期存在的进程(例如 DisposableEffect 或 LaunchedTask)。
    • (Id50b9)
  • MutableVector 现已实现 RandomAccess(I85d73b/170461551
  • 添加了 SideEffect 可组合项,用于将组合的附带效应应用到其管理的对象。SideEffect 旨在取代 onCommit 可组合项。(Ia77c2)
  • 新增了实验性 API RestorableStateHolder。通过该 API,可先为子树保存定义为 [savedInstanceState] 和 [rememberSavedInstanceState] 的状态,然后再对其进行处理,以便下次利用恢复后的状态将其重新组合起来。(I66884b/166586419

问题修复

  • 在 ComposeTestRule 中启用了过渡;从 ComposeTestRule 中移除了用于启用闪烁光标的选项。(If0de3)

版本 1.0.0-alpha05

2020 年 10 月 14 日

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

API 变更

  • 实验性 Modifier.pointerInput 挂起输入修饰符 (Ia77d2)
  • 通过减少每次滚动时 subcomposition 中的工作量,改善了 LazyColumn/Row 的滚动性能。为 Composition 类添加了新的 hasInvalidations() 方法。将 Recomposer 中的 hasPendingChanges() 方法重命名为 hasInvalidations()(Ib2f32b/168293643b/167972292b/165028371
  • 添加了 produceState API,用于从组合项启动可随时间的推移更新单个 State<T> 值的协程 (Id4a57)
  • 将 launchInComposition 重命名为 LaunchedTask,以符合 Compose API 准则 (I99a8e)
  • 自定义布局中 place() 调用的顺序现在可定义子级的绘制顺序 (Ibc9f6)

版本 1.0.0-alpha04

2020 年 10 月 1 日

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

API 变更

  • 添加了 OwnerScope,以允许收集失效的布局和绘制观察范围。(Ic4cf8)
  • 添加了 derivedStateOf API,可根据计算结果创建可以读取(和派生于)其他 State 对象的 State 对象 (If758b)
  • 为 SnapshotStateObserver 添加了 TestOnly API (I6e2a9)

问题修复

  • 弃用了 foundation.Box。请改用 foundation.layout.Box。(Ie5950b/167680279

版本 1.0.0-alpha03

2020 年 9 月 16 日

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

API 变更

  • CompositionCoroutineScope 不再实现 MonotonicFrameClockwithFrameNanos 的调用方应明确导入顶层函数。(Icb642b/166778123

问题修复

  • 全局测试函数(例如 onNodewaitForIdle)现已弃用,请改用根据 ComposeTestRule 定义的新函数 (I7f45a)
  • launchInComposition 不再启动未分派的协程(Ief6afb/166486000

版本 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 更改为 Function3 而非 Function1 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