Android中Flow重试无效,纠结选StateFlow还是SharedFlow?
问题背景
要实现点击Snackbar的重试按钮重新调用API,采用MVVM架构+纯Flow实现(原用LiveData,现要求仅用Flow)。最初写法重试功能无效,改成MutableStateFlow或MutableSharedFlow后纠结选型:当前仅支持竖屏,但担心未来有配置变更需求,不确定哪种Flow更合适。
初始无效代码
Fragment代码
private fun apiCall() { viewModel.fetchUserReviewData() } private fun setObservers() { lifecycleScope.launch { viewModel.userReviewData?.collect { LogUtils.d("Hello it: " + it.code) setLoadingState(it.state) when (it.status) { Resource.Status.ERROR -> showErrorSnackBarLayout(-1, it.message, { // 重试按钮逻辑 viewModel.userReviewData = null apiCall() }) } } } }
ViewModel代码
var userReviewData: Flow<Resource<ReviewResponse>>? = emptyFlow<Resource<ReviewResponse>>() fun fetchUserReviewData() { LogUtils.d("Hello fetchUserReviewData: " + userReviewData) userReviewData = flow { emit(Resource.loading(true)) repository.getUserReviewData().collect { emit(it) } } }
初始写法无效原因:每次调用
fetchUserReviewData都会创建新的Flow实例,Fragment订阅的是旧Flow,重试后新Flow的事件无法被收集到。
修改后可行代码
ViewModel代码(二选一)
// 选项1:MutableStateFlow // var userReviewData = MutableStateFlow<Resource<ReviewResponse>>(Resource.loading(false)) // 选项2:MutableSharedFlow var userReviewData = MutableSharedFlow<Resource<ReviewResponse>>() fun fetchUserReviewData() { viewModelScope.launch { userReviewData.emit(Resource.loading(true)) repository.getUserReviewData().collect { userReviewData.emit(it) } } } override fun onCreate() {}
Activity代码
private fun setObservers() { lifecycleScope.launchWhenStarted { viewModel.userReviewData.collect { setLoadingState(it.state) when (it.status) { Resource.Status.SUCCESS -> if (it.data != null) { val reviewResponse: ReviewResponse = it.data if (!AppUtils.isNull(reviewResponse)) { setReviewData(reviewResponse.data) } } Resource.Status.ERROR -> showErrorSnackBarLayout(it.code, it.message) { viewModel.fetchUserReviewData() } } } } }
选型分析
MutableStateFlow 适用场景
- 有初始值,始终持有当前最新状态,新订阅者会立即收到当前值
- 配置变更(如屏幕旋转)后,重建的Fragment/Activity会自动获取最新状态,无需重新发起请求,完美适配未来可能的配置变更需求
- 适合承载UI状态(如加载状态、数据结果)这类需要持久化的信息
MutableSharedFlow 适用场景
- 默认无初始值,仅向活跃订阅者发送新事件;若未设置
replay,配置变更后重建的订阅者无法收到之前的事件 - 适合发送一次性事件(如导航、弹出Toast),而非持久化的UI状态
最终选型建议
结合你的场景:这个Flow用来承载API请求的全流程状态(加载、成功、错误),属于UI状态范畴,且未来可能有配置变更需求,优先选择MutableStateFlow。
内容的提问来源于stack exchange,提问作者Ishika Singh
相关产品推荐
相关产品推荐

