如何在Fragment每次调用onResume时重新启动协程?
解决Fragment每次onResume重启协程的问题
你的代码问题在于launchWhenResumed只会在Fragment首次进入Resumed状态时执行一次协程逻辑,后续再次触发onResume时,这个协程已经完成或处于运行状态,不会重新执行内部的Flow收集逻辑,导致后续onResume没有反应。下面是两种正确的实现方式:
方法一:使用repeatOnLifecycle(官方推荐)
这是Jetpack Lifecycle库提供的最佳实践,它会自动在每次进入指定生命周期状态时执行逻辑,离开时取消协程,下次进入时重新启动。
val renderer = ... val outerFlow = ... val lifecycleScope = myFragment.viewLifecycleOwner.lifecycleScope lifecycleScope.launch { // 每次进入RESUMED状态时执行块内逻辑,离开时取消 repeatOnLifecycle(Lifecycle.State.RESUMED) { outerFlow.collect(renderer::render) // 如果你需要在collect前做额外处理,也可以用onEach: // outerFlow.onEach(renderer::render).collect() } }
原理:repeatOnLifecycle会监听生命周期变化,当Fragment进入RESUMED状态时,启动Flow的收集协程;当Fragment离开RESUMED(比如进入PAUSED)时,自动取消这个收集协程。下次回到RESUMED时,会重新启动收集,完美匹配每次onResume重启协程的需求。
方法二:手动监听生命周期回调
如果需要更手动的控制,可以在Fragment的onResume中启动协程,onPause中取消之前的协程:
private var renderJob: Job? = null val renderer = ... val outerFlow = ... override fun onResume() { super.onResume() // 每次onResume启动新的协程 renderJob = viewLifecycleOwner.lifecycleScope.launch { outerFlow.collect(renderer::render) } } override fun onPause() { // 离开时取消协程,避免泄漏 renderJob?.cancel() renderJob = null super.onPause() }
注意:这种方法需要手动管理Job的生命周期,不如repeatOnLifecycle优雅,容易出现遗漏取消的情况,因此优先推荐第一种方法。
内容的提问来源于stack exchange,提问作者Denis Perfomer
相关产品推荐
相关产品推荐

