LiveData type mistmatch in ViewModel

417 views Asked by At

I was following one of the UDACITYs Android Tutorial on LiveData/Room/Persistence and Repository Architecture.

After gluing the codes all together, I came across (what I believe, a very common issue) Type Mismatch exception.

On the course example, a VideosRepository was created with a member videos which is a LiveData:

class VideosRepository(private val database: VideosDatabase) {

/**
 * A playlist of videos that can be shown on the screen.
 */
    val videos: LiveData<List<Video>> =
        Transformations.map(database.videoDao.getVideos()) {
            it.asDomainModel()
        }

and in the Model, I have a introduce a MutableLiveData of _video

val playlist = videosRepository.videos //works fine

// added by me
private val _video = MutableLiveData<List<Video>>()
val video: LiveData<List<Video>> = _video

When I tried to access the LiveData, this is where I am getting the Type mismatch.

fun sample(){
   _video.value = videosRepository.videos //does not work and throws a Type mismatch.
   //Required: List<Video> Found: LiveData<List<Video>>
}

And if I try to just stuff all LiveData in the ViewModel (meaning, only the ViewModel will have the LiveData object declarations) and converting all LiveData to just plain List and a function such as

fun getVideos(): List<Video>{
    return database.videoDao.getVideo()
}

I would then get Cannot access database on the main thread since it may potentially lock the UI for a long period of time. which I understand clearly. So if that is the case, then LiveData is the only way to do it.

But how can I get away from the Type mismatch.

PS. I understand concepts of OOP as well as Java, but never had the in-depth hands-on experience, so please bear with me.

2

There are 2 answers

0
Uuu Uuu On

Input of _video.value is a List<Video> but you assigned videosRepository.videos that is a LiveData<List<Video>> You have to get List<Video> from LiveData :

_video.value = videosRepository.videos.value
0
Sơn Phan On

videosRepository.videos's data type is LiveData<List<Video>> but _video.value's data type is List<Video>, so you can't assign like that.

Try:

val video: LiveData<List<Video>> = videosRepository.videos

Then in the view, observe the livedata to do what you want with the data, an example in Fragment:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   ...
   viewModel.video.observe(viewLifecycleOwner, Observer {
      val data: List<Video> = it
      // Do something with the data such as showing it...
   })  
}

If you really want to have a MutableLiveData in case of modifying it later, use MediatorLiveData:

private val _video = MediatorLiveData<List<Video>>().apply {
   addSource(videosRepository.videos) {
      value = it
   }
}
val video: LiveData<List<Video>> = _video