HelloCW
HelloCW

Reputation: 2365

Why do I get null value of LiveData after I have used async{} in Android Studio with Kotlin?

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

Answers (1)

Wei
Wei

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

Related Questions