[英]LiveData not updating observer after Room database query
我有一個房間數據庫,其中有與藝術家相關的歌曲,當我從 Main Activity 溢出菜單更改藝術家時,除非我離開片段並再次返回,否則帶有顯示歌曲列表的 recyclerview 的片段不會更新。 我認為我對列表的觀察就足夠了,因為它適用於正在進行的其他更改,但這次不行。
當數據發生變化時,如何讓它更新新藝術家的歌曲?
歌曲視圖模型
//default artist name for this phase of production
var artistName = "Ear Kitty"
private val _artistNameLive = MutableLiveData<String>(artistName)
val artistNameLive: LiveData<String>
get() = _artistNameLive
private var _allSongs : MutableLiveData<List<SongWithRatings>> = repository.getArtistSongsWithRatings(artistNameLive.value.toString()).asLiveData() as MutableLiveData<List<SongWithRatings>>
val allSongs: LiveData<List<SongWithRatings>>
get() = _allSongs
fun changeArtist(artist: String){
_artistNameLive.value = artist
artistName = artist
updateAllSongs()
}
fun updateAllSongs() = viewModelScope.launch {
run {
_allSongs = repository.getArtistSongsWithRatings(artistNameLive.value.toString())
.asLiveData() as MutableLiveData<List<SongWithRatings>>
}
}
MainFragment當對所有歌曲進行更改時,觀察者工作得很好,但當它完全由不同的藝術家更新時就不行了。
songViewModel.allSongs.observe(viewLifecycleOwner) { song ->
// Update the cached copy of the songs in the adapter.
Log.d("LiveDataDebug","Main Fragment Observer called")
Log.d("LiveDataDebug",song[0].song.songTitle)
song.let { adapter.submitList(it) }
}
我發現一堆答案說要在我從 Main Activity 調用的 Fragment 中創建一個函數,但我不知道該函數會去哪里,因為我無法使適配器成為 onViewCreated 之外的成員。 起初我會得到一個錯誤,說適配器可能已經改變,然后我在下面嘗試了這個並得到了一個空指針異常。
主要片段
lateinit var adapter: ItemAdapter
fun notifyThisFragment(){
adapter.notifyDataSetChanged()
}
主要活動
songViewModel.changeArtist(artistList[which])
val navHostController = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
//I get the null pointer exception on the line below
val mainFrag: MainFragment = navHostController.childFragmentManager.findFragmentById(R.id.mainFragment) as MainFragment
mainFrag.notifyThisFragment()
據我了解,我的主要活動托管 navHostFragment,它是我的 MainFragment 的父片段。 我有什么問題嗎? 我應該這樣做有不同的方式嗎? 我試圖遵循建議的架構,而不是做一堆奇怪的工作。 我是否應該只從數據庫中獲取 allSongs 並在 songViewModel 中過濾它? 我不明白為什么 allSongs.observe 沒有得到改變。
我最終通過制作一個用於列表適配器的allArtistSongsWithRatings解決了這個問題。 我從allSongsWithRatings過濾列表以避免額外的數據庫查詢。 起初這是不成功的,因為當我嘗試過濾allSongsWithRatings時返回 null 。 事實證明,由於LiveData的工作方式,我需要在過濾之前觀察allSongsWithRatings 。 我在MainActivity和initializeArtist中觀察到allSongsWithRatings 。
主要活動
//initialize viewModel
songViewModel.allSongsWithRatings.observe(this){
songViewModel.initializeWithArtist()
}
主要片段
songViewModel.allArtistSongsWithRatings.observe(viewLifecycleOwner) { song ->
// Update the cached copy of the songs in the adapter.
Log.d("LiveDataDebug","Main Fragment Observer called")
//Log.d("LiveDataDebug",song[0].song.songTitle)
song.let { adapter.submitList(it) }
}
SongViewModel
var artistName = "Ear Kitty"
private val _artistNameLive = MutableLiveData<String>(artistName)
val artistNameLive: LiveData<String>
get() = _artistNameLive
private val _allSongsWithRatings : MutableLiveData<List<SongWithRatings>> = repository.allSongsWithRatings.asLiveData() as MutableLiveData<List<SongWithRatings>>
val allSongsWithRatings: LiveData<List<SongWithRatings>>
get() = _allSongsWithRatings
private val _allArtistSongsWithRatings = (artistNameLive.value?.let {
repository.getArtistSongsWithRatings(
it
).asLiveData()
} )as MutableLiveData<List<SongWithRatings>>
val allArtistSongsWithRatings: LiveData<List<SongWithRatings>>
get() = _allArtistSongsWithRatings
fun changeArtist(artist: String){
_artistNameLive.value = artist
artistName = artist
initializeWithArtist()
}
fun initializeWithArtist(){
var newList = mutableListOf<SongWithRatings>()
newList = allSongsWithRatings.value as MutableList<SongWithRatings>
//make sure the list isn't empty
if(newList.isNullOrEmpty()){
//handle empty list error
}else{
//list sorted by performance rating
_allArtistSongsWithRatings.value = newList.filter { it.song.artistName == artistNameLive.value } as MutableList<SongWithRatings>
allArtistSongsWithRatings.value
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.