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
相关产品推荐
相关产品推荐

