Iva
Iva

Reputation: 47

Is this a proper usage of Coroutines IO dispatcher in ViewModel?

I want to make sure if the following is a proper use of the IO dispatcher:

Would it be proper if I made use of it?

This is the code without the dispatchers

private suspend fun getNews() = viewModelScope.launch {
   _newsResponse.postValue(Resource.loading(null))
   try {
     repository.getNews().let {
       if (it.isSuccessful){
          _newsResponse.postValue(Resource.success(it.body()))
       }else{
          _newsResponse.postValue(Resource.error(it.errorBody().toString(), null))
       }
    }
}

And this is the code using IO Dispatcher

private suspend fun getNews() = viewModelScope.launch {
   withContext(Dispatcher.IO){

     _newsResponse.postValue(Resource.loading(null))
       try {
           repository.getNews().let {
           if (it.isSuccessful){
              _newsResponse.postValue(Resource.success(it.body()))
           }else{
              _newsResponse.postValue(Resource.error(it.errorBody().toString(), null))
          }
        }
    }
}
  1. What would be the proper way to do (with or without the IO dispatcher?
  2. Is withContext(Dispatcher.IO) same as when I do viewmodelscope.launch(IO)?

Upvotes: 1

Views: 2401

Answers (2)

Tenfour04
Tenfour04

Reputation: 93699

If repository.getNews() is a properly composed suspend function, you don’t need to specify a dispatcher at all. A properly composed suspend function doesn’t block, it suspends, so it is safe to call from any context without specifying dispatcher. An improperly composed suspend function would be one that internally calls a blocking function without internally specifying a dispatcher that can handle its type of blocking calls.

Retrofit provides suspend functions for making requests so you should be able to easily compose repository.getNews() in a proper way.

You also don’t need to be using liveData.postValue() since the view model scope is on the main dispatcher by default. You can use the standard value setter property.

Regarding your second question, these two ways of doing it would be equivalent in this specific case since you wrap the entire contents of your coroutine in the withContext block. But like I said, you don’t need to specify dispatcher at all so you should use a bare launch call.

Upvotes: 4

i30mb1
i30mb1

Reputation: 4776

  1. It depends on which dispatcher you want to run your job. If you want do it on IO or Main dispatchers that comes as default dispatcher for viewModelScope.
  2. viewModelScope.launch(IO) launches a new coroutine on IO dispatcher where withContext(Dispatcher.IO) only switch current coroutine dispatcher from current to IO.

Upvotes: 1

Related Questions