Jetpack Compose(4)——重组 - SharpCJ

Jetpack Compose(4)——重组 - SharpCJ

💡 原文中文,约9300字,阅读约需23分钟。
📝

内容提要

本文讨论了Compose中的状态重组,强调状态变化如何触发重组,并需创建新对象以确保重组发生。使用`mutableStateListOf`可以更优雅地管理状态。重组时,只有依赖状态变化的组件参与,从而确保性能。稳定性概念也很重要,使用`@Stable`注解可提升重组性能。最后总结了重组特性及优化方法。

🔎

延伸解读

状态变化判断:equals 比较与稳定性

Compose 通过 equals 比较 State 包裹的对象来判断状态是否变化,但这一规则仅适用于稳定类型。对于不稳定类型,即使引用未变,其内部属性可能被修改,导致 equals 结果不可靠。因此,Compose 会保守地触发重组,以避免 UI 显示错误。理解这一点有助于解释为何某些组件在参数未变时仍参与重组。

重组范围与 inline 函数的影响

重组范围最小化原则下,只有依赖状态变化的代码块参与重组。但 Column、Box 等 inline 函数会扩大重组范围,因为其内容被内联到调用处,导致父级作用域也被标记为 invalid。而 Card 等非 inline 函数则不会。这提醒开发者注意 inline 组件对重组性能的潜在影响。

使用 @Stable 提升重组性能

对于自定义 data class,若使用 var 声明属性,Compose 会视为不稳定类型,导致不必要的重组。通过添加 @Stable 注解,可让编译器将其视为稳定类型,从而在对象引用不变时跳过重组。@Immutable 用于完全不可变类型,但 @Stable 适用场景更广,建议优先使用。

重组线程与乐观执行

重组可能发生在后台线程,并可能并发执行,因此需注意线程安全。Compose 采用乐观策略:状态连续变化时,中间态重组可能被中断,但最终会依据最新状态完成,不会将中间结果反映到视图树。这保证了 UI 的最终一致性,但也要求开发者避免在重组中执行副作用。

❓

Q&A

Compose 中状态变化如何触发重组?

状态变化是指 State 包裹的对象进行 equals 比较,只有当比较结果不相等时,才会触发重组。

如何优雅地管理 Compose 中的状态?

可以使用 `mutableStateListOf` 来更优雅地管理状态,确保状态变化时触发重组。

什么是 @Stable 注解,它有什么作用?

@Stable 注解用于标记类型为稳定类型,从而提升重组性能,避免不必要的重组。

Compose 如何确保重组的性能优化?

Compose 只参与重组的组件是依赖于状态变化的,未变化的组件会跳过重组,从而优化性能。

使用 var 声明的类型在重组中会有什么影响?

使用 var 声明的类型可能被认为是不稳定类型,可能导致错误的 UI,因此建议使用 @Stable 注解。

Compose 中如何处理不稳定类型的状态变化?

可以使用 @Stable 注解来将不稳定类型视为稳定类型,从而提升重组性能。

🏷️

标签

➡️

继续阅读