LiveData调用Room DB时未使用更新后的songID参数问题求助
问题分析
你遇到的核心问题是:_trackList是初始化阶段一次性赋值的,调用getTracksBySongId(songID)时用的是初始值0;后续songID更新后,这个LiveData实例不会自动重新创建,导致查询永远使用旧的ID参数。
解决方案
方案1:用MutableLiveData + switchMap动态触发查询(推荐)
通过将songID改为可观察的LiveData,结合Transformations.switchMap监听其变化,自动触发新的数据库查询。
代码修改步骤:
- 将
songID改为LiveData类型:
private val _songID = MutableLiveData<Long>(0) val songID: LiveData<Long> = _songID
- 重新定义
_trackList,关联songID的变化:
private val _trackList: LiveData<List<Track>> = Transformations.switchMap(_songID) { id -> db.trackDao().getTracksBySongId(id) } val trackList: LiveData<List<Track>> get() = _trackList
- 在
createNewSong中更新songID的LiveData值:
suspend fun createNewSong(){ val newSong = Song(0, null, true, "Song ${songList.value?.size?.plus(1)}") val job = viewModelScope.async() { db.songDao().insert(newSong) } val newId = job.await() _songID.postValue(newId) // 协程中用postValue更新LiveData }
此后每次_songID的值变化,switchMap都会自动调用getTracksBySongId获取对应ID的最新LiveData,观察者能直接收到更新后的列表。
方案2:手动维护查询结果(不推荐,繁琐)
若不想用switchMap,可将_trackList改为MutableLiveData,每次songID更新后手动触发查询并更新值:
- 修改
_trackList类型:
private val _trackList = MutableLiveData<List<Track>>() val trackList: LiveData<List<Track>> get() = _trackList
- 新增查询方法:
private fun fetchTracksForSongId(id: Long) { viewModelScope.launch { // 用first()获取当前ID对应的Track列表 val tracks = db.trackDao().getTracksBySongId(id).first() _trackList.postValue(tracks) } }
- 在
createNewSong中更新songID后调用查询:
suspend fun createNewSong(){ val newSong = Song(0, null, true, "Song ${songList.value?.size?.plus(1)}") val job = viewModelScope.async() { db.songDao().insert(newSong) } songID = job.await() fetchTracksForSongId(songID) }
额外优化点
观察者中直接使用回调参数it,避免获取viewModel.trackList.value可能拿到旧值的问题:
val trackListObserver = Observer<List<Track>> { tracks -> adapter.submitList(tracks) } viewModel.trackList.observe(viewLifecycleOwner, trackListObserver)
内容的提问来源于stack exchange,提问作者SelfTitled
相关产品推荐
相关产品推荐

