-1

Source code can be found at : https://github.com/AliRezaeiii/TVMaze

I have following repository class :

class ShowRepository(
    private val showDao: ShowDao,
    private val api: TVMazeService
) {

    /**
     * A list of shows that can be shown on the screen.
     */
    val shows: LiveData<List<Show>> =
        Transformations.map(showDao.getShows()) {
            it.asDomainModel()
        }

    /**
     * Refresh the shows stored in the offline cache.
     */
    suspend fun refreshShows(): Result<List<Show>> = withContext(Dispatchers.IO) {
        try {
            val news = api.fetchShowList().await()
            showDao.insertAll(*news.asDatabaseModel())
            Result.Success(news)
        } catch (err: HttpException) {
            Result.Error(err)
        }
    }
}

As I understand Room does not support MutableLiveData rather it support LiveData. So I have created two object in my ViewModel to be observed :

class MainViewModel(
    private val repository: ShowRepository,
    app: Application
) : AndroidViewModel(app) {

    private val _shows = repository.shows
    val shows: LiveData<List<Show>>
        get() = _shows

    private val _liveData = MutableLiveData<Result<List<Show>>>()
    val liveData: LiveData<Result<List<Show>>>
        get() = _liveData

    /**
     * init{} is called immediately when this ViewModel is created.
     */
    init {
        if (isNetworkAvailable(app)) {
            viewModelScope.launch {
                _liveData.postValue(repository.refreshShows())
            }
        }
    }
}

I use show LiveData varialbe to submit list in my Activity :

viewModel.shows.observe(this, Observer { shows ->
            viewModelAdapter.submitList(shows)
        })

And I use LiveData variable to display error message when an exception occurs in refreshShows() of repository :

viewModel.liveData.observe(this, Observer { result ->
            if (result is Result.Error) {
                Toast.makeText(this, getString(R.string.failed_loading_msg), Toast.LENGTH_LONG).show()
                Timber.e(result.exception)
            }
        })

Do you think is there a better solution to have one LiveData in ViewModel rather than two?

Ali
  • 9,800
  • 19
  • 72
  • 152
  • What is the error you are getting? – OhhhThatVarun May 28 '20 at 10:37
  • It may happen that I get 404 error when I refresh shows. Please look at refreshShows() method in Repository class. I want to have exception handling. – Ali May 28 '20 at 10:38
  • So it is not handling the exception? The app is crashing? – OhhhThatVarun May 28 '20 at 10:41
  • My question is : Do you think is there a better solution to have one LiveData in ViewModel rather than two – Ali May 28 '20 at 10:44
  • I think you can improve ur code, using this repo as a base. It uses a single source of truth strategy using livedata. I think you will have to dig the repo a bit to understand the code, but to sum up, this code will get data from the api, store in ur room, and provide ur room query's anwer as a result, so observing this will do it all. https://github.com/Eli-Fox/LEGO-Catalog/blob/master/app/src/main/java/com/elifox/legocatalog/data/SingleSourceOfTruthStrategy.kt – Henrique Vasconcellos May 28 '20 at 12:50
  • 1
    @HenriqueVasconcellos, thank you for sharing the repo. It is what I was looking for. You can share your comment as answer and I mark it as accepted. – Ali May 28 '20 at 13:09

1 Answers1

0

I think you can improve ur code, using this repo as a base. It uses a single source of truth strategy using livedata. I think you will have to dig the repo a bit to understand the code, but to sum up, this code will get data from the api, store in ur room, and provide ur room query's anwer as a result, so observing this will do it all.

Henrique Vasconcellos
  • 1,144
  • 1
  • 8
  • 13
  • Hi, I dig into the repo and faced with an interesting issue that I shared here : https://stackoverflow.com/questions/62092123/refreshshows-in-repository-get-called-every-time-oncreate-callback-of-activi Do you know why? – Ali May 29 '20 at 19:31