Coroutinues and flow in Android apps

Tram Ho

  • For every Android application developer, we want to have a project that is neat, easy to maintain. Clean architecture will help us with that. The business logic will be at the center of the project, unrelated to the technology we use.
  • Because Clean Architecture has many layers, it is very important for data to easily move through the floors. With this, we can use Rx – a really powerful tool for reactive programing. Unfortunately it is often for use with background threads. Previous operations that started with Single and Completable (one-time actions where Rx is only used for easy flow switching) are actually very good alternatives to Coroutines.
  • There are many comparisons about Rx and Couroutines that this is not true because they are created for different uses. This article will distinguish between one-time actions when we use coroutines and observing data when we use Flow.

One-time actions

  • Kotlin provides couroutines support at language level. This is really easy to handle multitasking, suspend and resume tasks
  • Scope makes it easy to avoid basic errors. When starting a coroutine, start it with scope and all tasks will be canceled when we cancel scope. The Android Architecture Component defines ViewModelScope and LifecycleScope, but you can also create your own scope. The ViewModelScope is destroyed when the ViewModel is cleared and the LifecycleScope is attached to its owner lifecycle as a Fragment.

  • By default, ViewModelScope.lauch will be run on the main thread, so don’t forget to move too heavy tasks to another dispatcher in the repository or usecase. These functions should be marked with a suspend. Every suspend functioncos can change the dispatcher with withContext

The suspend function is really very effective. The excute function will be run on the dispatcher Defaullt. The binding of the user will be performed after the calculation, but on the main thread will not be blocked but supended. The main thread will be available to other tools until the user returns

WithContext () can also be used right inside viewModelScope.launch, but viewModel should not know the user’s execution. It is better to suspend the function in the domain and the data layer determines the dispatcher’s method and value when fetched or calculated. In this way every suspend function is concerned about its own dispatcher

  • Dispatchers.IO is often used to fetch data from the network, databases, etc. – operations that do not require much CPU
  • Dispatchers.Default should be used for computing or CPU intensive tasks. You can also return Dispatchers.Main (Android main thread) or use Dispatchers.Uninedined without changing the thread. It starts on the current thread, but if this function starts another pause function that changes the dispatcher, it will continue on that dispatcher.
  • If you need lots of results from different sources, you can use many coroutines with async:

  • It will start with 2 corountine for each fetch value. If coroutines are moved thread by thread (and not on Dispatcher.Main), creating the user object will take the longest possible time for the fetch operation. For example, processing value1 takes 3s, processing vaule 2 takes 5s. So user will be created in 5s, if using 1 coroutune will be 8s
  • Every couroutine can split itself this way without having too much knowledge about coroutine
  • Both launch and async return the Job, which you can check to see its status. You can use this if you don’t want to start couroutine with some other active coroutine


  • Coroutines are great for one-time actions, when you need to fetch or calculate something once
  • Although Kotlin flow lacks some powerful operators like Rx, it is hard to leave anything unmanaged

  • It will return to a Flow <User>. We can apply many operators in it, like debounce, which will filter out values ​​followed by newer values ​​over the time. Most operators can easily be written as Flow extention and we can find its source on blog or github.
  • After using all the operators you want, we can register the event with collect () or colectLast () . Then will cancel the previous value when the new value appears. If you put this code in your model or presenter, it won’t work. The reason is that the collect () function is a suspend function and it will force us to start with Flow tied to CoroutineScope. This way we will maintain the domain registry in its scope.

  • viewModelScope.lauch () will launch Flow on the dispatcher and, like coroutine, convert it to a dispacher domain or data

Flowon will affect all operators. Therefore this function can redefine the dispatcher for its operators and possible buildFlow () . flowOn for its set of operators. If you put it in a method, it will work like this.

So where does Flow come from? How to create them? There are several ways. You can use

  • Or you can use a channel similar to Dubject or Processor in Rx

Some libraries also allow us to observer via Flow like Room


Share the news now

Source : Viblo