如何在Kotlin Fragment的onResume中重启Coroutine并恢复上次位置
问题描述
我希望在应用中使用Coroutines和循环函数,要求Fragment进入onDestroyView生命周期时取消该协程任务,进入onResume时重新启动任务并从之前的位置继续执行。我已实现onDestroyView中的取消逻辑,但不清楚如何在onResume中重启并恢复执行位置,现有代码如下:
private val bannerJob = CoroutineScope(Main) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) bannerJob.launch { repeat(REPEAT_TIME) { delay(DELAY_TIME) if (autoScrollIndex < list.size) { autoScrollIndex += 1 } else { autoScrollIndex = 0 } binding.list.scrollToPosition(autoScrollIndex) } } } override fun onDestroyView() { super.onDestroyView() bannerJob.cancel() }
解决方案
要实现协程重启并从上次位置继续执行,需要调整几个核心逻辑,修改后的代码如下:
// 用Fragment自带的lifecycleScope替代自定义CoroutineScope,自动绑定生命周期 private var autoScrollIndex = 0 private var currentBannerJob: Job? = null override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) startBannerAutoScroll() } override fun onResume() { super.onResume() startBannerAutoScroll() } override fun onPause() { super.onPause() currentBannerJob?.cancel() } override fun onDestroyView() { super.onDestroyView() currentBannerJob?.cancel() } private fun startBannerAutoScroll() { // 先取消已有任务,避免多个协程同时运行 currentBannerJob?.cancel() currentBannerJob = lifecycleScope.launch { while (isActive) { // 基于协程存活状态实现无限循环,取消时自动终止 delay(DELAY_TIME) // 简化索引循环逻辑 autoScrollIndex = (autoScrollIndex + 1) % list.size binding.list.scrollToPosition(autoScrollIndex) } } }
关键说明
- 协程作用域选择:使用
lifecycleScope(Fragment内置协程作用域),它会在Fragment销毁时自动取消所有协程,避免内存泄漏,比自定义CoroutineScope更安全。 - 任务管理:用
currentBannerJob变量跟踪当前运行的协程,每次启动前先取消旧任务,确保同一时间只有一个轮播协程在执行。 - 状态保留:
autoScrollIndex作为Fragment成员变量,只要Fragment实例未被销毁,就能保留上次的位置,重启协程时直接从该位置继续。 - 循环逻辑优化:用
(autoScrollIndex + 1) % list.size替代原有的条件判断,代码更简洁且能实现无限循环轮播。 - 生命周期绑定:在
onPause和onDestroyView中取消任务,在onViewCreated和onResume中重启,保证Fragment可见时轮播运行,不可见时暂停。
如果需要在Fragment销毁后仍保留autoScrollIndex,可以将其存入SavedStateHandle(配合ViewModel使用),确保配置变更或Fragment重建时不丢失状态。
内容的提问来源于stack exchange,提问作者Dali Hasan
相关产品推荐
相关产品推荐

