Architecture Components: Easy Mapping of Actions and UI State

Tram Ho


When building an Android application, most of the time what we are doing is mapping actions directly, or indirectly, actions to some state of the UI.

In the process of using Architecture Components, achieving this is quite easy with the help of LiveData + Coroutine + ViewModels, but it also requires a bit of source code to set up for it.

The reason is that in order to listen for the “states” of a LiveDat, we must write a wrapper of its values, as well as integrate actions around these states.

Let’s take an example, there is a list based on UI where:

  • data is downloaded from an API.
  • User can swipe-refresh and try calling API again if there is an error, etc.

To meet these requirements, actions will be:

  • Load
  • Swipe Refresh
  • Retry

And based on these actions, the UI state can be one of these at any given moment:

  • Success
  • Loading
  • Swipe-Refreshing
  • Failure
  • SwipeRefresh-Failure
  • Retrying

The State Machine

If we had mapped the states to the actions mentioned above using an expression – It should look like this:

Actions can be clear or implicit. The difference is that clear actions (shown by blue arrows) are actions caused by the user and implicit actions are not.

Let’s code it out!


Starting with State, create a wrapper that represents states using sealed classes .


Similar to states, we will create a wrapper to represent actions


We will need to re-customize LiveData to handle all actions and spit out appropriate states based on them (similar to what reducers do in Redux).

It is also advisable to make API calls using Coroutines and pass exceptions.

The implementation process is as follows:

Process using new liveData block (which is actually suspend block) and emit method – We can execute source code asynchronously and emit values.

The switchMap block is also a new syntax for implementing Transformations.switchMap () on a mutable LiveData.

The last part is the method for submitting actions.


As we discussed Coroutines, we will specify scope as viewModelScope and use Dispatchers.IO as the coroutine context.

viewModelScope —> Attaches our Coroutine lifecycle to ViewModel lifecycle.

Dispatchers.IO —> Execute the coroutine block asynchronously.

UI (Fragment / Activity)

Once all is done – The UI is pretty easy, we initialize the viewModel to generate the initial load action and listen for the results.

So that’s how it is now – This is a basic example of how we can use LiveData + Coroutine + ViewModel to map actions to UI States. These make it a little more difficult to deal with with pagination and unorthodox UI rules. We will also generalize them in the future.




P / S

Posts on my viblo, if there is a Source section, then this is a translation from the source that is linked to the original post in this section. These are the articles I select + search + synthesized from Google in the process of handling issues when making real + projects useful and interesting for myself. => Translated as an article to rummage through when necessary. Therefore, when reading the article, everyone should note:

1. You can go to the source to read the original article (extremely recommend).

2. Translated article => Can not avoid misunderstanding, omission, confusion due to differences in language, context as well as understanding of the translator => We hope you can leave comments to complete the problem.

3. The translation is for reference only + has the true meaning of a translated article requested by the company.

4. Hope the article helps you a bit (I hope so!). =)))))))

Share the news now

Source : Viblo