生产环境App因onResume连续调用引发并发修改异常崩溃求助
Activity连续触发onResume->onPause->onResume的场景分析及修复建议
一、触发该生命周期序列的常见场景
- 屏幕唤醒/锁屏过渡:这是你观察到的高频场景。设备从锁屏唤醒时,系统可能先恢复Activity的
onResume,随后因锁屏过渡界面、状态栏通知刷新等系统窗口短暂抢占焦点,触发onPause,焦点回归后再次调用onResume。不同定制ROM的锁屏逻辑差异会放大这种快速切换。 - 系统配置快速变更:比如屏幕方向因传感器误判、系统bug或第三方工具被连续触发切换,系统会在重建Activity前触发一次
onResume->onPause,完成配置变更后再次调用onResume。 - 多窗口/焦点快速切换:支持分屏的设备上,其他应用快速抢占或释放焦点(如快速拖拽分屏边界、系统弹窗快速弹出又消失),会导致当前Activity焦点快速变化,触发该生命周期序列。
- 第三方组件干扰:无障碍服务、悬浮窗应用或系统工具可能短暂获取窗口焦点,导致Activity快速失焦又重新获焦。比如权限弹窗自动快速关闭、悬浮球的高频交互操作。
- 应用内组件快速操作:若在
onResume中触发Dialog快速显示隐藏,或Fragment快速添加移除,可能引发宿主Activity焦点快速变化,触发生命周期的快速切换。
二、针对ConcurrentModificationException的修复方案
你的崩溃源于onResume中启动的IO协程并发操作同一列表,可通过以下方式解决:
- 使用线程安全集合:将普通
ArrayList替换为CopyOnWriteArrayList,该集合在修改时会复制底层数组,避免并发修改异常。 - 协程绑定生命周期并自动取消:使用
lifecycleScope(Activity级)或viewModelScope(跨生命周期)启动协程,在Activity进入onPause时,未完成的协程会被自动取消,避免并发操作。示例代码:
override fun onResume() { super.onResume() lifecycleScope.launch(Dispatchers.IO) { // 安全执行列表操作逻辑 } }
- 添加防抖逻辑:对
onResume中的协程启动逻辑做防抖处理,设置合理延迟(如300ms),若期间再次触发onResume则取消前一次任务,避免重复启动。示例:
private var resumeTask: Job? = null override fun onResume() { super.onResume() resumeTask?.cancel() resumeTask = lifecycleScope.launch(Dispatchers.IO) { delay(300) // 执行列表操作 } } override fun onPause() { super.onPause() resumeTask?.cancel() }
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

