Solution 1 :
Your code can actually be simplified by removing async-await
and it will work the same.
binding.button.setOnClickListener {
val aa = mHomeViewModel.listVoice().value // It will be null too.
}
The code inside async { ... }
is not how you probably think it works. To explain this;
-
LiveData.getValue()
is not a suspending function. Hence, theasync { ... }
returns immediately. -
LiveData.getValue()
is intended to get its current value without waiting for next first value. This is the reason why it’s not a suspending function.
Problem :
The Code A query LiveData<List<MVoice>>
with Room and display them in RecyclerView
control, it works well.
I know that query LiveData with Room will be run in a background thread, so val dd
will return null in Code B.
I think val bb
will return correct List<MVoice>
in Code C, but in fact, it return null, why ?
Code A
binding.button.setOnClickListener {
mHomeViewModel.listVoice().observe(viewLifecycleOwner){ listMVoice->
adapter.submitList(listMVoice)
}
}
@Dao
interface DBVoiceDao{
@Query("SELECT * FROM voice_table ORDER BY createdDate desc")
fun listVoice():LiveData<List<MVoice>>
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
fun listVoice()= mDBVoiceDao.listVoice()
}
class HomeViewModel(private val mDBVoiceRepository: DBVoiceRepository) : ViewModel() {
fun listVoice()= mDBVoiceRepository.listVoice()
}
Code B
binding.button.setOnClickListener {
val dd=mHomeViewModel.listVoice().value //It return null
}
... //It's the same as Code A
Code C
binding.button.setOnClickListener {
lifecycleScope.launch{
val aa=async { mHomeViewModel.listVoice() }
val bb=aa.await().value //It return null too
}
}
... //It's the same as Code A
Comments
Comment posted by HelloCW
Thanks! but you know that
Comment posted by Wei
@HelloCW Yeah, it’s the exact same thing like in Code B.
Comment posted by HelloCW
Thanks! Do you mean that
Comment posted by Wei
@HelloCW You’re welcome. Practically, not always. But in your case, it is. You can replace the