Managing Jetpack Compose UI State With Sealed Classes | by Lucca Beurmann | May, 2022

Use Sealed Lessons to deal with doable states of composable views

Photograph by Anderson Rian on Unsplash

Updating the UI to adapt to a given state is a daily job for many Android builders. One of the vital frequent efforts is transitioning between loading, error, and success states coming from an API request.

Managing UI state within the XML View System is a fairly normal course of normally composed of setting the view’s properties to replicate the present state and hiding/exhibiting views in response to necessity. For instance, hiding the loading view, exhibiting the content material view, and populating it with the specified content material. There’s not a lot to speak about this course of apart from its main flaw: human error.

In your profession as an Android Developer, you could have in all probability stared at a ViewBinding primarily based display for a number of minutes (and even hours for actually complicated layouts) attempting to grasp why your UI just isn’t updating appropriately, to after a while uncover that you simply forgot a myView.visibility = View.GONE , this can be a widespread mistake brought on by the handbook effort to replace your views for each doable state.

Jetpack Compose is designed to allow the creation of precise reactive screens by the utilization of the State class, altering the worth of a State triggers the recomposition of Composable features that relies on this identical state, in different phrases, if our State object holds a String worth a brand new composition will likely be triggered each time it adjustments, offering the up to date String worth with out the necessity of handbook set strategies. The identical is legitimate for each mixture State<T> so if our UI state is held inside a state object we are able to routinely replace the UI for each state change.

However sufficient speaking, let’s do some actual code.

First, let’s create a sealed class liable for describing the doable states of our display, this explicit use case requires 3 completely different instances: loading, error, and prepared.

Gist1: Making a UIState sealed class

Discover that on this state of affairs the one state that incorporates any knowledge is Success , it’s because our use case would not want any further data for loading or error states.

Our use case follows the MVVM sample so our display’s present state will likely be saved in a ViewModel.

A personalMutableStateFlow will likely be used to carry the UI state, a public StateFlow to propagate this data for our Compose view, and a mocked implementation utilizing a delay to simulate the loading state brought on by the async request.

Since we all know that an API request will likely be launched as quickly because the ViewModel is instantiated, we are able to safely assume the beginning state of our display is loading.

With the AlbumState setup prepared, we’ll transfer to the UI and make it react and recompose in response to the present state saved within the ViewModel.

This structure consists of two completely different Composable features, AlbumScreen which incorporates the injected ViewModel, and its stateless companion Content material, liable for the structure configuration.

Content material incorporates a default Materials Design Scaffold containing a TopBar and a when case, being the final one liable for informing what must be displayed for each AlbumState. When working the app we are able to see that our conduct is working as anticipated.

Previews can be utilized to assist builders to see a visible illustration of the Compose UI being written.

To keep away from relaunching the app to see the visible results of each state we are able to use a Preview annotated operate alongside a PreviewParameter supplier to render a singular preview for all of our states.

By doing that we are able to assert two issues: the structure of every display is appropriately designed, and the truth that all of the doable states are mutually unique.

Declaring a PreviewParameterProvider<T> permits the utilization of this supplier in Preview annotated features, the best way it really works is {that a} new preview will likely be generated for each worth contained within the values sequence.

Now on the design tab, we are able to see the opposite previews generated for every state:

The display state is now saved on the ViewModel so it is fascinating to write down unit assessments to ensure that the states are being up to date appropriately. Because the UI’s state is a StateFlow, we are able to use the Turbine library to make it simpler to gather each worth of our movement simply.

Checks under had been written with Kotlin coroutines model 1.6.1. Check API may change in response to the model you’re utilizing.

Instrumented assessments are very helpful to ensure that composables are displaying the proper structure for a given state. These assessments will be written with the compose normal library for UI assessments.

On this case for every of the states, a distinct composable will likely be used, so it is doable so as to add a take a look at tag for use in our take a look at. The take a look at tags will function identifiers for our take a look at, so we are able to assert which part is being proven on the display.

Sealed states are very helpful when the UI has a set of mutually unique layouts. This strategy (if applied appropriately) ensures that just one display state is seen at any given time, avoiding doable bugs brought on by a number of states being rendered on the identical time.

When the UI would not must have mutually unique layouts the utilization of sealed lessons to deal with state will not be helpful in any respect, generally, being even an issue that solely causes a rise in state administration complexity. For these instances desire utilizing a single knowledge class containing the knowledge you want.

A full pattern code is out there right here:

More Posts