Reputation: 2365
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
Upvotes: 3
Views: 448
Reputation: 1036
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, the async { ... }
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.
Upvotes: 4