Skip to content
DeveloperMemos

Using derivedStateOf in Jetpack Compose

Android, Jetpack, Compose, Kotlin1 min read

When you're working with states in Jetpack Compose and you want to merge, combine or run some complex logic on them derivedStateOf really comes in handy for computation. If you're familiar with React it kind of reminds me of useMemo with dependencies. In this post I'll go through a simple example of how to use it with a counter app.

So say for example you have two states already, a first and second counter that keep track of the state for two counters:

1var firstCount by remember {
2 mutableStateOf(0)
3}
4
5var secondCount by remember {
6 mutableStateOf(0)
7}

And you wanted to create a new state variable that calculates the total of the two values and returns whether or not they exceed 10. You can use deriveStateOf like this:

1val totalIsOver10 by remember {
2 derivedStateOf {
3 val total = firstCount + secondCount
4 total > 10
5 }
6}

This will return a Boolean which you can then use in your UI/Composables, like this for example:

1Text(if (totalIsOver10) "Total is over 10" else "Total is less than 10")

Why even use deriveStateOf?

If you're thinking this, you're right - you could just define a variable without using remember or deriveStateOf and the example above would still work. The reasoning behind using deriveStateOf specifically is that it will limit the number of recompositions, because you are telling Compose what should trigger a recomposition. You can read more about this in the documentation, with some more indepth examples here and here.

The rest of the code

Below is the full Composable for the example I discussed above with the two counters, if you are interested and wanted to take a look. I also suggest reading the two documentation links I linked in the previous paragraph if you want to go for a bit of a deep dive.

1import androidx.compose.foundation.layout.Arrangement
2import androidx.compose.foundation.layout.Column
3import androidx.compose.foundation.layout.fillMaxSize
4import androidx.compose.material.Button
5import androidx.compose.material.Text
6import androidx.compose.runtime.*
7import androidx.compose.ui.Alignment
8import androidx.compose.ui.Modifier
9import androidx.compose.ui.tooling.preview.Preview
10
11@Composable
12fun CounterScreen() {
13 var firstCount by remember {
14 mutableStateOf(0)
15 }
16
17 var secondCount by remember {
18 mutableStateOf(0)
19 }
20
21 val totalIsOver10 by remember {
22 derivedStateOf {
23 val total = firstCount + secondCount
24 total > 10
25 }
26 }
27
28 Column(
29 modifier = Modifier.fillMaxSize(),
30 verticalArrangement = Arrangement.Center,
31 horizontalAlignment = Alignment.CenterHorizontally,
32 ) {
33 Text(if (totalIsOver10) "Total is over 10" else "Total is less than 10")
34 Button(
35 onClick = { firstCount += 1 }
36 ) {
37 Text(text = "Increment(Count 1)")
38 }
39 Button(
40 onClick = { secondCount += 1 }
41 ) {
42 Text(text = "Increment(Count 2)")
43 }
44 }
45}
46
47@Preview
48@Composable
49fun CounterScreenPreview() {
50 CounterScreen()
51}