在 Jetpack Compose 中,理解可组合项的生命周期对于构建高效且响应迅速的用户界面至关重要。可组合项的生命周期描述了从首次组合到退出组合的整个过程,以及在此期间可能发生的多次重组。
生命周期概览
可组合项的生命周期通过以下事件定义:
- 进入组合:当可组合项首次被调用并加入到组合树中时。
- 执行重组:零次或多次。当应用状态发生变化时,可能触发重组,重新执行受影响的可组合项。
- 退出组合:当可组合项不再需要并从组合树中移除时。
图示:进入组合 → 执行 0 次或多次重组 → 退出组合
初始组合与重组
- 初始组合:当 Jetpack Compose 首次运行可组合项时,它会跟踪所有为了描述界面而调用的可组合项,构建初始的组合树。
- 重组:当应用状态发生变化时,Compose 会安排受影响的可组合项重新执行,更新组合树以反映这些变化。重组是修改组合的唯一方式。
重组的触发
重组通常由对 State<T> 对象的更改触发。Compose 会跟踪这些状态变化,并重新执行所有读取了该状态的可组合项。
可组合项实例的管理
- 调用点标识:可组合项的实例由其调用点(即调用可组合项的源代码位置)唯一标识。从多个调用点调用同一可组合项会在组合中创建多个实例。
- 保留身份:在重组期间,保留可组合项的身份对于附带效应(如网络请求、动画等)的正确执行至关重要。这确保了附带效应不会在每次重组时都重新启动。
智能重组与跳过
- 跳过条件:在重组期间,如果可组合项的输入与上次组合相比未发生变化,则可以跳过该函数的执行。这要求所有作为参数传递给可组合项的类型都是稳定的。
- 稳定类型:稳定类型是指其值在相等性检查中始终保持一致,且其任何公共属性的变化都会通知组合的类型。包括基元值类型(如 Boolean、Int、Long 等)、字符串、函数类型(lambda)以及某些被显式标记为稳定的类型(使用
@Stable注解)。 - 强跳过(实验性):一种实验性编译器模式,可放宽对稳定类型的最后一个要求,允许更灵活地跳过重组。
使用 key 可组合项优化重组
- 问题:当从同一调用点多次调用可组合项时,仅使用调用点可能无法唯一标识每个实例,导致意外行为。
- 解决方案:使用
key可组合项封装代码块,指定用于在组合中标识该实例的值。这有助于 Compose 在重组期间正确识别和重复使用可组合项实例。 - 示例:
@Composable fun MoviesScreenWithKey(movies: List<Movie>) { Column { for (movie in movies) { key(movie.id) { // 使用 movie.id 作为唯一键 MovieOverview(movie) } } } }
内置支持
某些可组合项(如 LazyColumn)提供了对 key 的内置支持,允许在 items DSL 中直接指定自定义键。
总结要点
- 可组合项的生命周期包括进入组合、执行零次或多次重组、然后退出组合。
- 重组通常由状态变化触发,是修改组合的唯一方式。
- 可组合项的实例由其调用点标识,保留身份对附带效应至关重要。
- 如果可组合项的输入在重组期间未发生变化,则可以跳过执行。
- 使用稳定类型和
key可组合项可以优化重组性能。
通过深入理解可组合项的生命周期及其管理方式,开发者可以构建出更加高效和响应迅速的 Android 应用界面。