You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Navigation Components跳转至第二个Fragment后无法获取数据库数据

问题根源分析

  1. Repository的SharedFlow无重播配置:你在shareIn中未指定replay参数,默认值为0。这意味着当第一个Fragment的订阅取消后,SharedFlow不会保留之前发射的数据;第二个Fragment订阅时,只有数据库发生新的变更才会收到数据,无法获取已存在的历史数据。
  2. ViewModel存在冗余协程:每次调用getBaseCurrency()都会启动新的collect协程,若多次触发会导致重复发射状态,浪费资源且可能引发逻辑混乱。

修复方案

1. 修改Repository的SharedFlow配置

添加replay=1,让SharedFlow保留最近一次数据,确保新订阅者能立即获取已有数据:

val baseCurrency: Flow<BaseCurrencyModel> =
    currencyDAO.getBaseCurrency().shareIn(
        scope, 
        SharingStarted.WhileSubscribed(5000L),
        replay = 1 // 保留最近一次发射的数据
    )

2. 优化ViewModel实现

用stateIn直接转换Flow,替代手动collect到SharedFlow的逻辑,自动协程生命周期管理:

// 两个Fragment的ViewModel都可采用此写法
val baseCurrency: StateFlow<DatabaseState> = databaseRepository.baseCurrency
    .map { DatabaseState.Success(it.baseCurr) }
    .catch { emit(DatabaseState.Error(it.cause)) }
    .stateIn(
        viewModelScope,
        SharingStarted.WhileSubscribed(5000L),
        DatabaseState.Loading // 可选:添加加载初始状态
    )

3. 简化Fragment的订阅逻辑

无需调用getBaseCurrency(),直接collect转换后的StateFlow:

// Fragment 1
viewLifecycleOwner.lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        mViewModel.baseCurrency.collect { baseCurrency ->
            when (baseCurrency) {
                is DatabaseState.Success<*> -> {
                    mBinding.latestBase.text = String.format(getString(R.string.formatted_base_currency, baseCurrency.data))
                }
                is DatabaseState.Error<*> -> {
                    Log.i(TAG, "onCreateView: ERROR $baseCurrency")
                }
                is DatabaseState.Loading -> {
                    // 可选:处理加载状态
                }
            }
        }
    }
}

// Fragment 2
viewLifecycleOwner.lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        mViewModel.baseCurrency.collect { baseCurrency ->
            when (baseCurrency) {
                is DatabaseState.Success<*> -> {
                    Log.i(TAG, "onCreateView: ${baseCurrency.data}")
                }
                is DatabaseState.Error<*> -> {
                    Log.i(TAG, "onCreateView: ERROR $baseCurrency")
                }
                is DatabaseState.Loading -> {
                    // 可选:处理加载状态
                }
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者katowicenocom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 18:47:08