ArcTouch Android developers share 12 ways to improve JetPack Compose composable functions — and take your app to the next level.
5 min. read - July 13, 2023
Jetpack Compose is a modern toolkit for building native Android user interfaces (UIs) with Kotlin programming language. It is a declarative UI framework that enables developers to create and manage UI components with less code and complexity.
When used correctly, Jetpack Compose can help Android developers create beautiful and responsive apps more easily and efficiently. However, that requires understanding how to define UI components using functions that build UI elements. These functions are called “composables” and they can be combined to create complex interfaces. Composables make it easy to create highly reusable UI components that can be shared across multiple screens and applications.
Here are 12 best practices to improve your composable functions and take your Android app project to the next level.
As the name suggests, a modifier is used to modify the composable. They are especially important for public components, allowing customization whenever it’s used in your app. Below is an example of what you should avoid and what you should consider doing.
DON’T DO THIS…
1
2
3
4
5
6
INSTEAD, DO THIS…
1
2
3
4
5
6
7
8
9
10
Public composables that have a modifier as a parameter should include the default value Modifier
. It should appear as the first optional parameter after all the required parameters:
DON’T DO THIS…
1
2
3
4
5
6
7
8
9
INSTEAD, DO THIS…
1
2
3
4
5
6
7
8
9
The Modifier from the parameter should be used by a single layout node in the composable function. If the provided modifier is used by multiple composables at different levels, unwanted behavior can happen as having the wrong customization of your composable function.
DON’T DO THIS…
1
2
3
4
5
6
7
8
INSTEAD, DO THIS…
1
2
3
4
5
6
7
8
For better testability, always inject the ViewModel
into the composable as a parameter with a default value instead of creating it within the composable. This approach allows you to easily provide a mock ViewModel
while testing, which in turn enables you to test your composable functions in isolation without relying on the actual implementation of the ViewModel
.
DON’T DO THIS…
1
2
3
4
5
INSTEAD, DO THIS…
1
2
3
4
5
6
ViewModel
s have a longer lifetime than the composition because they survive configuration changes. Because of their long lifetime, ViewModel
parameters should not hold long-lived references to state bound to the lifetime of the composition. If they do, it could cause memory leaks.Instead, pass down the relevant data to the function and optional lambdas for callbacks.In addition, previews don’t work with ViewModel
, which makes it harder to preview your layout.
DON’T DO THIS…
1
2
3
4
5
6
INSTEAD, DO THIS…
1
2
3
4
5
6
7
8
9
10
Make sure to use remember
with a mutableStateOf
(or any other state builders). Otherwise, a new state instance will be created when the function is recomposed, causing app performance issues such as slow screen rendering and inconsistent state.
DON’T DO THIS…
1
2
3
4
5
6
7
8
9
INSTEAD, DO THIS…
1
2
3
4
5
6
7
8
9
A composable function should emit either 0 or 1 piece of layout, but no more. A composable function should be cohesive and not rely on the function that is called.The wrong example below shows that MyComposable
is being called from a column, but this might not be true. MyComposable
could also be called from a row, which would cause the wrong behavior.
1
2
3
DON’T DO THIS…
1
2
3
4
5
6
INSTEAD, DO THIS…
1
2
3
4
5
6
7
8
OR DO THIS…
1
2
3
4
5
6
CompositionLocals
should be named by using the adjective Local
as a prefix, followed by a descriptive noun that describes the value they hold. This makes it easier to know when a value comes from a CompositionLocal
. Given that these are implicit dependencies, make them obvious.
DON’T DO THIS…
1
INSTEAD, DO THIS…
1
With multipreview, you can define an annotation class that itself has multiple @Preview
annotations with different configurations. Adding this annotation to a composable function will automatically render all the different previews at once.
Multipreview annotations should be named by using Previews
as a suffix (or Preview
if just one). These annotations have to be explicitly named to make sure that they are clearly identifiable as a @Preview
alternative.
DON’T DO THIS…
1
2
3
4
5
6
7
8
9
10
11
INSTEAD, DO THIS…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Composable functions that return Unit should start with an uppercase letter. They are considered declarative entities that can be either present or absent in a composition — and, therefore, they follow the naming rules for classes.
However, composable functions that return a value should start with a lowercase letter instead. They should follow the standard Kotlin coding conventions for the naming of functions for any function annotated @Composable
that returns a value other than Unit
.
DON’T DO THIS…
1
2
OR THIS…
1
2
OR THIS…
1
2
OR THIS…
1
2
INSTEAD, DO THIS…
1
2
OR DO THIS…
1
2
OR DO THIS…
1
2
In Kotlin, it’s a good practice to write the mandatory parameters first, then the optional ones. This reduces the number of times you need to write the name of the arguments explicitly.
In addition, composables that have the Modifier
as a parameter should name the parameter modifier and assign the parameter a default value of Modifier
. It should appear as the first optional parameter in the parameter list.
DON’T DO THIS…
1
2
3
4
5
6
INSTEAD, DO THIS…
1
2
3
4
5
6
A @Preview
composable function doesn’t need to have public visibility because it won’t be used in the UI. Making them private
will prevent folks from using them unknowingly.
DON’T DO THIS…
1
2
3
INSTEAD, DO THIS…
1
2
3
ArcTouch has been building lovable Android apps for companies of all sizes since the dawn of the app store. Learn more about ArcTouch’s Android development services and contact us for a free consultation.
Get our newsletter in your inbox.
We help companies of all sizes build lovable apps, websites, and connected experiences.