MVVM with Coroutine Flow and Unit Tests in Kotlin — Part 1

ChandraSaiMohan bhupathi
4 min readJul 12, 2021

1.Before you begin:

In this blog we will learn how to use Coroutines with Flows and also unit tests with MVVM architecture in Kotlin.

What is Coroutine ?

A coroutine is a concurrency design pattern that you can use on Android to simplify code that executes asynchronously.

What is Flow ?

  • A flow is a stream of values that are asynchronously computed.
  • Flows emits values and there is other process/coroutines that receives/process the emitted values.

Prerequisites:

  • Familiarity with the Architecture Components ViewModel, LiveData, Repository.
  • Experience with Kotlin syntax, including lambdas.
  • A basic understanding of using threads on Android, including the main thread, background threads, and callbacks.

What you’ll do ?

  • Code written with coroutines and flows to fetch data from server and obtain results.
  • Use MVVM Architecture.
  • Use suspend functions to make async code sequential.
  • Use coroutines with Architecture Components.
  • Learn best practices for testing coroutines and flows.

2.Getting Setup :

The code is available in the above Github repository.

git clone https://github.com/chandragithub2014/MMVMCoroutineFlows.git

3.Run the app:

Architecture Used:

MVVM architecture is used to build this app

1.MainActivity :displays the UI. It observes data from ViewModel through live data and populates the list.

2. ViewModel : ViewModel handles the business logic using Coroutines and collects the data from Repository .

3. Repository: Communicates with Network to fetch the data in the form of flow which ViewModel collects in the coroutine.

4. Network : Handles Network communication.

Adding Coroutines to Project:

The below are the dependencies to be added to include coroutines in project:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"
coroutine_version = '1.3.9'

Using Coroutines in ViewModel:

class EmployeeViewModel(private val dispatcher: CoroutineDispatcher, private val employeeRepository: EmployeeRepository) : ViewModel(),LifecycleObserver {
var loading: MutableLiveData<Boolean> = MutableLiveData()
private val _employeeMutableLiveDate= MutableLiveData<UserModel>()
val employeeLiveData: LiveData<UserModel> = _employeeMutableLiveDate

init {
loading.postValue(true)
}
/**
* Fetch employee list
*
*/
fun fetchEmployeeList(){

viewModelScope.launch(dispatcher) {
loading.postValue(true)
try{
employeeRepository.fetchEmployees().collect { response->
if(response.isSuccessful){
loading.postValue(false)
val employeeInfo = response.body()
employeeInfo?.let { model ->
_employeeMutableLiveDate.value = model
}


}else{
loading.postValue(false)
}

}


}catch (e:Exception){
loading.postValue(false)
e.printStackTrace()
}
}

}

Explanation of above code:

As mentioned above coroutines help us to simplify that executes Asynchronously.

It uses suspend functions to avoid blocking the main thread.

The main thread is a single thread that handles all updates to the UI. It’s also the thread that calls all click handlers and other UI callbacks. As such, it has to run smoothly to guarantee a great user experience.

All Coroutines run inside a scope called CoroutineScope. A scope controls the lifetime of coroutines.

Scopes also allow you to specify a default dispatcher. A dispatcher controls which thread runs a coroutine.

For coroutines started by the UI, it is typically correct to start them on Dispatchers.Main which is the main thread on Android. A coroutine started on Dispatchers.Main won't block the main thread while suspended. Since a ViewModel coroutine almost always updates the UI on the main thread, starting coroutines on the main thread saves you extra thread switches. A coroutine started on the Main thread can switch dispatchers any time after it's started. For example, it can use another dispatcher to parse a large JSON result off the main thread.

Libraries like Room and Retrofit offer main-safety out of the box when using coroutines, so you don't need to manage threads to make network or database calls.

Coroutines with JetPack Components:

With Kotlin coroutines, you can define a CoroutineScope, which helps you to manage when your coroutines should run. Each asynchronous operation runs within a particular scope.

Architecture components provide first-class support for coroutines for logical scopes in your app along with an interoperability layer with LiveData.

Architecture components defines the following built-in scopes that you can use in your app which reduces the code to handle coroutine scopes.

ViewModelScope :

The above code fragment uses Viewmodelscope which is defined for each viewmodel in your app.

Any coroutine launched in this scope is automatically canceled if the ViewModel is cleared. Coroutines are useful here for when you have work that needs to be done only if the ViewModel is active.

For more info on Architecture components scopes please find below link:

https://developer.android.com/topic/libraries/architecture/coroutines

The above code fragment collects the data from the repository which returns flow of data received from network.

Code Fragment for Repository class that uses flow:

class EmployeeRepository(private  val apiServiceAPI: EmployeeService) {

suspend fun fetchEmployees() : Flow<Response<UserModel>> {
return flow {
val employeeInfo = apiServiceAPI.fetchEmployee()
emit(employeeInfo)
}
}
}

The above code uses suspend function to fetch data from network and returns the data as flow by emit() function.

Network layer:

Its an interface that contains Retrofit methods.

interface EmployeeService {
//https://reqres.in/api/users
@GET("/api/users")
suspend fun fetchEmployee(): Response<UserModel>
}

The next part of this blog will explain how to unit test Flows

https://b-chandrasaimohan.medium.com/mvvm-with-coroutine-flow-and-unit-tests-in-kotlin-part-2-54d4fc679641

--

--