为何SharedFlow调用collect后后续代码行始终无法执行
现象产生的核心原因
这是协程、SharedFlow、repeatOnLifecycle三者的默认行为共同导致的,不属于逻辑bug:
- 首先是SharedFlow的收集挂起特性:无参构造的
MutableSharedFlow是无限存续的热流,没有自动终止的逻辑。对它调用collect后,挂起函数会永久停留在收集位置等待新事件,永远不会正常返回并执行后续代码——除非承载收集操作的协程被主动取消。只有收集的是会正常结束的有限流(比如固定数据的冷流)时,collect才会在数据发完后返回,继续走后续逻辑。 - 其次是**
repeatOnLifecycle的协程取消规则**:这个API的设计逻辑不是“生命周期符合条件时执行一次代码块直到跑完”,而是“生命周期达到目标状态时启动代码块协程,生命周期跌出目标状态时直接取消正在运行的协程,等状态恢复再重新启动块”。协程取消是通过抛出CancellationException实现的异常式中断,会直接打断协程内的正常顺序执行流,collect后面的日志代码根本没有调度执行的机会。
不管是旋转屏幕触发的Activity配置变更重建,还是返回上一页触发的Activity销毁,都会让生命周期跌出STARTED状态,直接触发协程取消,永远走不到collect之后的顺序代码。
如果你需要在收集被停止时执行收尾逻辑,不要把代码写在
collect后面,改用try-finally包裹收集逻辑即可,finally块中的代码在协程取消时一定会被执行:lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED){ try { viewModel.sharedFlow.collect{ Log.i("View","Here can be call.") } } finally { Log.i("View","this line will be called when collect stops") } } }
内容的提问来源于stack exchange,提问作者JLin
相关产品推荐
相关产品推荐

