Splash Screen with Jetpack Compose: Side-Effects & How to Use Them

Daniel Dimovski
5 min readFeb 10, 2023

--

The Android developer documentation defines side-effect as a change to the state of the app that happens outside the scope of a composable function. This change can be as simple as showing a snackbar, or navigating to a different screen. There are different types of side-effects & we are going to look into some of them in this article through a practical example — creating a splash screen with Jetpack Compose. For this purpose I will use a sample project from one of my previous articles.

So, let’s add a splash screen to this project. First of all, we’ll need to create a new screen & setup Compose Navigation (in order to navigate between screens). I won’t go into details about Compose Navigation — that’s a topic for another time. Let’s create the new screen:

It is a simple screen that only shows a book icon in the center of the screen. Boring.

A splash screen doesn’t make much sense if we are not doing anything in the background, some validations, network operations etc. Since this is a sample application, I will use a dummy function that is supposed to validate the user details (spoiler alert: it doesn’t). We will only pass the outcome of the validation to the composable and use its value to animate the book colour. If the validation is successful, the book should turn green, and if it is unsuccessful, the book should turn red. Let’s do that:

However, this code will not work. It won’t even compile, because the animateTo() is a suspend method, and you can’t run suspend methods in a composable. That is, if you don’t use a side-effect. The LaunchedEffect, in particular.

LaunchedEffect

We will use the valid variable as the key for this side effect. This means that whenever the value of valid changes, the code in the LaunchedEffect will execute. Exactly what we need.

To call suspend functions safely from inside a composable, use the LaunchedEffect composable. When LaunchedEffect enters the Composition, it launches a coroutine with the block of code passed as a parameter.

I would also like to add some analytics to the splash screen. Let’s track each time the screen has been shown. How do we do that? If it was a regular Fragment or an Activity, we could use the lifecycle methods. But we can’t do that with composables. What we can do instead, is use another side effect — the DisposableEffect.

DisposableEffect

For side effects that need to be cleaned up after the keys change or if the composable leaves the Composition, use DisposableEffect

We will add a lifecycle observer and listen for the ON_START event. It is important to remember to clean up the DisposableEffect by using the onDispose callback.

And finally, for this to be a splash screen, it should eventually perfrom an action after some delay. We’ll again use the LaunchedEffect for this purpose, with a small tweak.

LaunchedEffect that runs only once

As explained earlier, LaunchedEffect executes every time its key value changes. But, what if we did not provide a variable key? What if we use a constant value? In that case, the LaunchedEffect will only execute once, when it is added to the composition. It won’t execute again after recomposition (that is, if it is not a part of a conditional statement).

We are using null as a key for the LaunchedEffect. This will cause the side-effect to only run once, when added to the composition (same happens if we used trueas a key). Let’s add a delay and run the method provided to the composable after the time passes. Looks good, the SplashScreen now behaves like one.

Warning: LaunchedEffect(true) is as suspicious as a while(true). Even though there are valid use cases for it, always pause and make sure that's what you need.

Note: If the LaunchedEffect is a part of a conditional statement & the result of that conditional changes, the LaunchedEffect will be removed/added from/to the composable, causing it to run again.

LaunchedEffect + rememberUpdatedState()

Let’s assume that we want to take different actions after the splash screen delay has passed, based on the result of the validation. Should be simple:

This code has a bug in it. The onSplashEndedValid will never get executed. Although it is not obvious at first, it makes sense if you think about it. We’ve already mentioned that the LaunchedEffect with null or true as a key runs only once. This means it will take the initial value of valid into consideration, the value it has when the LaunchedEffect was added to the composition. The SplashScreen will be recomposed later with the new value of valid , but the LaunchedEffect won’t know about this new value. So, in the code above, the valid == true condition will always result in false. This is where rememberUpdatedState() comes into play. It creates a reference to the value that can be updated, so when the LaunchedEffect block executes the code, it has the up-to-date value, rather the one it had when the LaunchedEffect was first added to the composition.

And there we have it, a simple splash screen created in compose, utilising various side effects to reach our goal:

There are a few other ways to utilise the Effects API in Jetpack Compose that did not have a valid use case in our splash screen. You can read more about them in the official documentation, where you can also find more technical description of what was presented in this article. The purpose of the article was to provide practical examples of using the different side-effects in Android & understand the difference between them.

The full code can be found here:

And here you can see the PR with changes made for this article:

If you are curious about the original project, take a look at the article How to Use the Android Paging3 Library With Jetpack Compose

--

--