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

ViewModel如何观察列表?MediatorLiveData的onChange未触发问题排查

问题1:闪屏页提前启动数据库加载是否合理

该实践完全合理,属于常用的启动页预加载优化方案:既不会拖慢闪屏页的跳转节奏,又能把数据库加载的时机提前,减少主页面用户的等待时长,符合性能优化的核心思路。而且你采用的LiveData自带粘性特性,就算数据库加载在主页面初始化前就完成了,主页面开始观察后也能立刻拿到已经加载好的数据,适配性很好。

问题2:MediatorLiveData的onChange不触发的原因与修复

核心原因

你创建的pokemonListMediator没有被任何观察者绑定,LiveData的规则是只有处于活跃状态(存在至少一个活跃观察者)时才会触发数据源的回调,你只是给MediatorLiveData添加了数据源,但是从来没有对它调用observe方法,所以它永远不会响应仓库数据的变化。
另外你的写法冗余了,不需要额外维护两个LiveData,直接把MediatorLiveData暴露给UI层观察即可。

修复代码

调整后的ViewModel代码

// 直接把MediatorLiveData暴露给Activity观察,不需要额外维护pokemonList变量
val pokemonList: MediatorLiveData<MutableList<Pokemon>> = MediatorLiveData()

init {
    // 观察仓库层的LiveData,有变化直接更新自身的值
    pokemonList.addSource(PersistenceSingletonRepository.listOfPokemon) { list ->
        Log.d("POKEMON", "onChange")
        pokemonList.value = list
    }
}

fun loadLists() {
    // 初始化时先取当前已有值,已经加载完成的话可以直接拿到数据
    pokemonList.value = PersistenceSingletonRepository.listOfPokemon.value
}

主Activity的代码不需要修改,还是按照原有逻辑观察pokemonList即可,只要Activity开始观察,MediatorLiveData就会被激活,仓库层的列表更新会自动触发回调。

额外优化建议

  • 闪屏页的协程最好绑定页面生命周期,用lifecycleScope启动,不要用全局CoroutineScope,避免内存泄漏
  • 仓库层的LiveData最好对内用MutableLiveData存储、对外暴露不可变的LiveData,避免外部随意修改值:
private val _listOfPokemon = MutableLiveData<MutableList<Pokemon>>()
val listOfPokemon: LiveData<MutableList<Pokemon>> = _listOfPokemon

// 内部赋值用私有可变实例
CoroutineScope(Dispatchers.Main).launch {
    _listOfPokemon.value = list
}
  • 注意统一类名写法,你现有代码里PersistenceSingleton和PersistenceSingletonRepository名字混用,容易出现引用错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:51:03