The Modern Mobile

A regular digest with everything you need to know about modern mobile development.

By JetBrains & Kotlin Community

Subscribe to keep up with all the important news, tutorials, and tips & tricks related to modern declarative frameworks, tools for cross-platform mobile development, and more.

Check out the latest newsletter ⬇️

Latest: Jetpack Compose tips & tricks from industry experts

Jetpack Compose is a modern toolkit for building native UIs. It simplifies and accelerates UI development on Android. Like any powerful tool, however, learning all the best practices and figuring out how to use it to its full potential takes time and dedication. We asked some industry experts to share their favorite tips & tricks for using Jetpack Compose. We hope you’ll be able to use them in your projects and unleash the full power of this framework!

Igor Demin, JetBrains

If your application is fully written with Jetpack Compose, you can disable activity recreation on some configuration changes. Just add this to your activity in AndroidManifest.xml:


Compose handles these changes very well by itself. The UI will be smooth and responsive, without breaking intermediate animations. This is especially important if your application is running on a foldable device, on a tablet, or on ChromeOS, where the window may be resizable. Note that you still need to keep all your important states in ViewModel or in rememberSaveable to restore them when needed – for example upon process restore or when going back in the navigation stack.

If you are starting to develop a new application on Jetpack Compose, consider writing it in a multiplatform style, so that the core functionality doesn't depend on the platform’s API. Check out this template, which shows how to do this using Compose Multiplatform. You can write a lot of code that can be used not only on Android but also on desktop platforms, as well as some code for web platforms. We have plans to add support for additional platforms, so stay tuned.
Anna Zharkova, UseTech, Google Developer Expert

To optimize a Compose app and provide better performance, pay attention to keeping and managing its state.

There are several APIs you need to use in order to manage the state: remember, mutableStateOf, and rememberSaveable.

The remember API is used to store an object in memory. A value computed by remember is stored in the Composition during initial composition, and the stored value is returned during recomposition. The remember API can be used to store both mutable and immutable objects. In each recomposition, remember returns the stored object so the composable can use it. If the object is mutable then whenever it has to change, you can update it and remember will preserve its state. The next time a recomposition occurs, remember will provide the object with the state from the previous recomposition.

Be careful: remember stores objects in the Composition and forgets the object when the composable that called remember is removed from the Composition. The state is not retained across configuration changes either.

The mutableStateOf() function creates an observable MutableState<T>, which is an observable type integrated with the Compose runtime. To keep the state and prevent it from resetting on the next recomposition, combine remember and mutableStateOf.

If you don’t want to disable activity recreation when certain configuration changes are made (such as a change of orientation or state, for example, as Igor mentioned), you need to think about how to keep your data when it is recreated. You can do this using the rememberSaveable(). It allows you to restore your UI state after an activity or process is recreated. It automatically saves any value that can be saved in a Bundle and retains the state across recompositions and throughout activity and process recreation. For other values, you can pass in a custom saver object.

You can find some best practices here:
Michael Friend, TouchLab

Avoid mutable collections and vars in objects used as state in Compose. Recomposition depends on equality checks between what the state was and what it is now. When you mutate an object by adding an item to a mutable list or setting a var property in a state object, the new and old states refer to the same object, so it will never be seen as changed. Instead use the SnapshotList/Map types, which can be cast to a MutableList/Map but will cause recomposition on change. For state-holder objects, always use val properties and create a new object for each update.

val data by mutableStateOf(MyData(title = "Title"))
data.title = "New Title"
var list by mutableStateOf(mutableListOf("a"))
// DO
var data by mutableStateOf(MyData(title = "Title"))
data = data.copy(title = "New Title")
val list = mutableStateListOf("a")
// OR
var list by mutableStateOf(listOf("a"))
list = list + "b"

Know the difference between the Effect functions: DisposableEffect is for when you need to do cleanup work. LaunchedEffect is for when you need to call a suspend function. And SideEffect is for all other cases. Use all of these sparingly and think carefully about the `key` parameter to avoid unnecessary work and recomposition.

Subscribe and get more tips, tricks, and other useful modern mobile development content in your inbox every month.