切换至其他Activity时协程未取消,Activity中如何实现类似处理?
你当前的代码中,lifecycleScope绑定的是Activity的完整生命周期,只有当Activity走到DESTROYED状态(被销毁)时才会自动取消协程。而切换到其他Activity时,当前Activity仅进入STOPPED或PAUSED状态,并未被销毁,所以协程会持续运行。
Fragment中使用viewLifecycleOwner能生效,是因为viewLifecycleOwner的生命周期绑定了Fragment视图的创建与销毁——切换Fragment时,原Fragment的视图会被销毁(VIEW_DESTROYED),对应的协程也就被取消了。
方法一:使用repeatOnLifecycle(官方推荐)
Jetpack Lifecycle库提供的repeatOnLifecycle方法可以让协程仅在Activity处于指定生命周期状态时运行,当Activity离开该状态时自动取消协程。最适配的状态是STARTED——当Activity处于前台(可见)时协程运行,进入后台(不可见)时协程被取消。
代码示例:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) lifecycleScope.launch { // 仅在Activity处于STARTED或RESUMED状态时执行块内代码 repeatOnLifecycle(Lifecycle.State.STARTED) { while (true) { delay(5000) Log.i(TAG, "From lifecyclescope") } } } }
当你切换到其他Activity,当前Activity进入STOPPED状态,repeatOnLifecycle会自动取消内部的协程,日志输出停止;当切回该Activity,它重新进入STARTED状态,协程会再次启动并继续执行。
方法二:手动监听生命周期取消协程
如果需要更灵活的控制,可以持有协程的Job引用,在Activity进入后台时手动取消:
private var coroutineJob: Job? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) coroutineJob = lifecycleScope.launch(Dispatchers.IO) { while (true) { delay(5000) Log.i(TAG, "From lifecyclescope") } } } override fun onStop() { super.onStop() // 进入后台时取消协程 coroutineJob?.cancel() coroutineJob = null // 避免内存泄漏 }
这种方法需要手动管理协程的生命周期,不如repeatOnLifecycle优雅;如果需要Activity回到前台时重启协程,还需额外处理重启逻辑。
内容的提问来源于stack exchange,提问作者Metropol_Tilkisi

