> 文档中心 > Google推荐在Compose中使用collectAsStateWithLifecycle替代collectAsState

Google推荐在Compose中使用collectAsStateWithLifecycle替代collectAsState


写在前面

生命周期感知方式收集流是在 Android 上收集流的推荐方式。 如果您使用 Jetpack Compose 构建 Android 应用程序,请使用 collectAsStateWithLifecycle API 从您的UI以生命周期感知的方式收集流。

collectAsStateWithLifecycle 允许您的应用在不需要时保存应用资源,例如当应用在后台时。 不必要地保持资源活动可能会影响用户的设备运行状况。 此类资源可能包括 Firebase 查询、位置或网络更新以及数据库连接。

collectAsStateWithLifecycle

collectAsStateWithLifecycle 是一个可组合函数,它从流中收集值并以生命周期感知的方式将最新值表示为 Compose State。 每次发生新的流发射时,此 State 对象的值都会更新。 这会导致组合中每个 State.value 使用的重新组合。

默认情况下,collectAsStateWithLifecycle 使用 Lifecycle.State.STARTED 开始和停止从流中收集值。 这发生在生命周期移入和移出目标状态时。 您可以在 minActiveState 参数中配置此生命周期状态。

 以下代码片段演示了如何使用 collectAsStateWithLifecycle 来收集可组合函数中的 ViewModel 已暴露的 StateFlow 的 uiState 字段:

@OptIn(ExperimentalLifecycleComposeApi::class)@Composablefun AuthorRoute(  onBackClick: () -> Unit,  modifier: Modifier = Modifier,  viewModel: AuthorViewModel = hiltViewModel()) {  val uiState: AuthorScreenUiState by viewModel.uiState.collectAsStateWithLifecycle()  AuthorScreen(    authorState = uiState.authorState,    newsState = uiState.newsState,    modifier = modifier,    onBackClick = onBackClick,    onFollowClick = viewModel::followAuthorToggle,  )}

每次 AuthorViewModel 的 uiState 发出一个新的 AuthorScreenUiState 值时,都会重新组合 AuthorRoute。

要开始在您的项目中使用 collectAsStateWithLifecycle API,请将 androidx.lifecycle.lifecycle-runtime-compose 工件添加到您的项目中。

dependencies {    implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.0-alpha01"}

底层实现 

在底层,collectAsStateWithLifecycle 的实现使用了 repeatOnLifecycle API,这是在 Android 中使用 View 系统收集流的推荐方式。

collectAsStateWithLifecycle 使您无需键入下面显示的样板代码,该样板代码还以生命周期感知的方式从可组合函数中收集流:

@Composablefun AuthorRoute(...) {    val lifecycle = LocalLifecycleOwner.current.lifecycle    val uiState by produceState(        initialValue = viewModel.uiState.value        key1 = lifecycle        key2 = viewModel    ) {        lifecycle.repeatOnLifecycle(state = STARTED) {            viewModel.uiState.collect { value = it }        }    }    AuthorScreen(...)}

在架构中使用 

你的应用架构中的类型不应该知道其他类型的实现细节。 UI 不应该知道 ViewModel 如何产生 UI 状态。 如果 UI 在屏幕上不可见,则应停止流收集以释放应用程序资源(如果合适)。

UI 可以通过使用 collectAsStateWithLifecycle 收集 UI 状态来帮助释放资源。 ViewModel 可以通过以收集器感知的方式生成 UI 状态来执行相同的操作。 如果没有收集器,例如当 UI 在屏幕上不可见时,请停止来自数据层的上游流。 您可以在生成 UI 状态时使用 .stateIn(WhileSubscribed) 流 API 执行此操作。 

 流的消费者和生产者不需要知道彼此是如何实现的。 在具有多个环境、变体、库和功能的大型应用程序中找出实现细节可能非常耗时。 更糟糕的是,维护依赖于实现细节的代码非常困难。

在后台保持资源活跃

Android 应用程序可以在无数的 Android 设备上运行。不幸的是,并非所有设备和所有用户都拥有无穷无尽的资源。应用程序通常在受限环境中运行。运行 Android 应用时,有一些重要因素会影响用户体验和设备系统健康:

  • CPU 使用率:在所有设备组件中,CPU 的电池消耗量最高。电池寿命是用户长期关注的问题。如果被滥用,用户可能会卸载您的应用。
  • 数据使用:在未连接到 Wi-Fi 时减少应用程序中的网络流量可以帮助用户节省资金。
  • 内存使用:应用程序如何使用内存会对设备的整体稳定性和性能产生非常大的影响。

根据设备类型和设备运行的 Android 版本,保持不需要的资源处于活动状态可能会产生负面影响。在 UI 层中使用 collectAsStateWithLifecycle 可以使层次结构的其余部分释放资源。

与collectAsState 比较

开发者经常会问:如果 collectAsStateWithLifecycle 是从 Android 中的可组合函数中收集流的最安全方式,为什么我们现在需要 collectAsState API? 或者为什么不将生命周期感知功能添加到 collectAsState 而不是创建新的 API?

可组合函数的生命周期与 Compose 运行的平台无关。 如可组合的生命周期页面中所述,可组合函数的实例进入组合,重新组合 0 次或更多次,然后离开组合。

collectAsState API 遵循组合的生命周期。 它在可组合项进入组合时开始收集流,并在离开组合时停止收集。 collectAsState 是与平台无关的 API,可用于收集流。

但是,在 Android 应用程序中使用 Compose 时,Android 生命周期在如何管理资源方面也起着至关重要的作用。 即使 Compose 在 Android 应用程序处于后台时停止重新组合,collectAsState 也会使集合保持活动状态。 这使得层次结构的其余部分无法释放资源。

collectAsState 和 collectAsStateWithLifecycle 在 Compose 中都有一个用途。 后者用于开发安卓应用,前者用于其他平台开发。

从 collectAsState 迁移到 collectAsStateWithLifecycle 很简单:

+ @OptIn(ExperimentalLifecycleComposeApi::class)@Composablefun AuthorRoute(    onBackClick: () -> Unit,    modifier: Modifier = Modifier,    viewModel: AuthorViewModel = hiltViewModel()) {-   val uiState: AuthorScreenUiState by viewModel.uiState.collectAsState()+   val uiState: AuthorScreenUiState by viewModel.uiState.collectAsStateWithLifecycle()    AuthorScreen(        authorState = uiState.authorState,        newsState = uiState.newsState,        modifier = modifier,        onBackClick = onBackClick,        onFollowClick = viewModel::followAuthorToggle,    )}

以生命周期感知方式收集流是在 Android 上收集流的推荐方式,以使您的应用程序的其他部分能够在需要时释放资源。

如果您使用 Jetpack Compose 构建 Android 应用程序,请使用 collectAsStateWithLifecycle 可组合函数来执行此操作。

佳庆纺织毛巾批发中心