假设我们有一个简单的片段,其中的视图基于视图模型中
StateFlow
中保存的 UI 状态。
在 onCreate()
,我们像往常一样收集状态:
override fun onCreate(savedInstanceState: Bundle?) {
lifecycleScope.launchWhenStarted {
viewModel.uiState.collect {
// UI update according to state
}
}
}
现在我们导航到下一个片段 - 前一个片段由片段管理器保留,但视图被破坏。在新片段上,我们弹出堆栈,现在令人惊讶的是: 前一个片段正在重新创建初始状态的视图,即使我们尝试更新状态流也不会发生任何事情,因为它不会一一发出两次相同的数据。
那么,返回fragment后如何恢复视图状态呢?
也许会晚一点,但您正在寻找的是repeatOnLifeCycle
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { ... }
}
}
repeatOnLifecycle 与生命周期作用域.launch 一起允许您从片段或活动收集流。
与您的方法的主要区别在于,launchWhenStarted 将在 UI State 启动后运行您的收集函数,但在恢复片段时不会重复收集,而 RepeatOnLifeCycle 将在每次生命周期范围达到时创建一个新的协程来启动收集指定状态(因此得名),并在生命周期到达相反状态时取消它(例如,如果指定 STARTED,则协程将在 onStop 时取消)。
除此之外,现在的 launchWhenX 文档还指出了以下内容
注意:该接口不建议使用,会导致资源浪费 某些情况下的资源。请使用 Lifecycle.repeatOnLifecycle API 代替。该 API 将在未来版本中删除。
PD,lifecycleScope.launch { ... } 创建一个协程,并且是必需的,因为 RepeatOnLifecycle 是一个挂起函数(挂起函数在协程或另一个挂起函数上运行)