And*_*rew 28 android android-fragments kotlin android-livedata
我使用 Flow 而不是 LiveData 来收集片段中的数据。在 Fragment AI 中,观察(或者更确切地说收集)我的片段 onViewCreated 中的数据,如下所示:
lifecycleScope.launchWhenStarted {
availableLanguagesFlow.collect {
languagesAdapter.setItems(it.allItems, it.selectedItem)
}
}
Run Code Online (Sandbox Code Playgroud)
问题。然后,当我转到片段 B 然后返回片段 A 时,我的收集函数被调用两次。如果我再次访问片段 B 并返回 A - 那么收集函数将被调用 3 次。等等。
And*_*rew 45
发生这种情况是因为Fragment 生命周期很棘手。当您从片段 B 返回到片段 A 时,片段 A 会重新附加。结果,片段的 onViewCreated 被第二次调用,并且您第二次观察 Flow 的相同实例。换句话说,现在你有一个流和两个观察者,当流发出数据时,其中两个被调用。
在Fragment的onViewCreated中使用viewLifecycleOwner。更具体地说,使用viewLifecycleOwner .lifecycleScope.launch 而不是 LifecycleScope.launch。像这样:
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
availableLanguagesFlow.collect {
languagesAdapter.setItems(it.allItems, it.selectedItem)
}
}
Run Code Online (Sandbox Code Playgroud)
在 Activity 中,您可以简单地在 onCreate 中收集数据。
lifecycleScope.launchWhenStarted {
availableLanguagesFlow.collect {
languagesAdapter.setItems(it.allItems, it.selectedItem)
}
}
Run Code Online (Sandbox Code Playgroud)
扩大:
fun <T> Flow<T>.launchWhenStarted(lifecycleOwner: LifecycleOwner) {
lifecycleOwner.lifecycleScope.launchWhenStarted {
this@launchWhenStarted.collect()
}
}
Run Code Online (Sandbox Code Playgroud)
在片段 onViewCreated 中:
availableLanguagesFlow
.onEach {
//update view
}.launchWhenStarted(viewLifecycleOwner)
Run Code Online (Sandbox Code Playgroud)
我宁愿使用 now repeatOnLifecycle,因为当生命周期低于状态时(在我的例子中是 onStop ),它会取消正在进行的协程。如果没有repeatOnLifecycle,则在 onStop 时收集将被暂停。看看这篇文章。
fun <T> Flow<T>.launchWhenStarted(lifecycleOwner: LifecycleOwner)= with(lifecycleOwner) {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED){
try {
this@launchWhenStarted.collect()
}catch (t: Throwable){
loge(t)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11426 次 |
| 最近记录: |