---
title: 12 Ways to Improve Jetpack Composable Functions | ArcTouch
description: ArcTouch Android developers share 12 ways to improve JetPack Compose composable functions — and take your app to the next level.
url: "https://arctouch.com/blog/jetpack-composable-functions"
date_modified: "2025-10-27T20:43:54.999Z"
---
# 12 ways to improve your Jetpack Compose composable functions

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

By Douglas Fornaro

[](mailto:?subject=Interesting%20blog%20post&body=I%20thought%20you%20might%20like%20this%20blog%20post%20from%20ArcTouch%3A%20https%3A%2F%2Farctouch.com%2Fblog%2Fjetpack-composable-functions)

![Jetpack Composable Functions best practices blog post](/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fefnbmai9c55m%2F6b7a2mbdu9ZBs1fgssnuXw%2Fa01cbfb362b580bdcefe96cfbfc3ec9d%2Fjetpack-composable-functions-blog-hero&w=3840&q=75)

[Jetpack Compose](https://developer.android.com/jetpack/compose) is a modern toolkit for building native Android user interfaces (UIs) with [Kotlin](/blog/kotlin-android-programming-language) 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](/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.

## 1\. Add a modifier for layout composables

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

```
@Composable
fun MyComposable() {
  Column {
    ...
  }
}
```

**INSTEAD, DO THIS…**

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

```
@Composable
fun MyComposable(
  modifier: Modifier = Modifier 
) {
  Column(
    modifier = modifier
  ) {
    ...
  }
}
```

## 2\. Include default parameters with modifiers

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

```
@Composable
private fun MyComposable(
  modifier: Modifier,
  list: List<String>,
) {
  Column(modifier) {
    ...
  }
}
```

**INSTEAD, DO THIS…**

1

2

3

4

5

6

7

8

9

```
@Composable
private fun MyComposable(
  list: List<String>,
  modifier: Modifier = Modifier
) {
  Column(modifier) {
    ...
  }
}
```

## 3\. Do not reuse modifiers

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

```
@Composable
private fun MyComposable(modifier: Modifier = Modifier) {
  Column(modifier) {
    Text(modifier.clickable(), ...)
    Image(modifier.size(), ...)
    Button(modifier, ...)
  }
}
```

**INSTEAD, DO THIS…**

1

2

3

4

5

6

7

8

```
@Composable
private fun MyComposable(modifier: Modifier = Modifier) {
  Column(modifier) {
    Text(Modifier.clickable(), ...)
    Image(Modifier.size(), ...)
    Button(Modifier, ...)
  }
}
```

## 4\. Inject ViewModel into the composable

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

```
@Composable
fun MyComposable() {
  val viewModel by viewModel()
  // ...
}
```

**INSTEAD, DO THIS…**

1

2

3

4

5

6

```
@Composable
fun MyComposable(
  viewModel: MyViewModel = viewModel()
) {
  // ...
}
```

## 5\. Do not forward the ViewModel

`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

```
@Composable
fun MyComposable(
   viewModel: MyViewModel = viewModel()
) {
  OtherComposable(viewModel)
}
```

**INSTEAD, DO THIS…**

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

```
@Composable
fun MyComposable(
  viewModel: MyViewModel = viewModel()
) {
  val uiState = viewModel.uiState.collectAsState()
  OtherComposable(
    data = uiState.data,
    onSaveButtonClicked = viewModel::onSaveButtonClicked
  )
}
```

## 6\. Use remember state in composables

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

```
@Composable
fun MyComposable() {
  val count = 0
  Button(onClick = { count++ }) {
    Text("Increase Count")
  }

  Text(text = "Count: $count")
}
```

**INSTEAD, DO THIS…**

1

2

3

4

5

6

7

8

9

```
@Composable
fun MyComposable() {
val count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Increase Count")
}

Text(text = "Count: $count")
}
```

## 7\. Do not emit multiple pieces of content

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

```
Column {
  MyComposable()
}
```

**DON’T DO THIS…**

1

2

3

4

5

6

```
@Composable
private fun MyComposable() {
  Text(...)
  Image(...)
  Button(...)
}
```

**INSTEAD, DO THIS…**

1

2

3

4

5

6

7

8

```
@Composable
private fun MyComposable() {
  Column {
    Text(...)
    Image(...)
    Button(...)
  }
}
```

**OR DO THIS…**

1

2

3

4

5

6

```
@Composable
private fun ColumnScope.MyComposable() {
  Text(...)
  Image(...)
  Button(...)
}
```

## 8\. Name CompositionLocals properly

`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

```
val ThemeLocal = compositionLocalOf { ... }
```

**INSTEAD, DO THIS…**

1

```
val LocalTheme = compositionLocalOf { ... }
```

## 9\. Name multipreview annotations properly

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

```
@Preview(
  name = "small font",
  group = "font scales",
  fontScale = 0.5f
)
@Preview(
  name = "large font",
  group = "font scales",
  fontScale = 1.5f
)
annotation class PreviewsFontScale
```

**INSTEAD, DO THIS…**

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

11

12

13

14

15

16

17

```
@Preview(
  name = "small font",
  group = "font scales",
  fontScale = 0.5f
)
@Preview(
  name = "large font",
  group = "font scales",
  fontScale = 1.5f
)
annotation class FontScalePreviews

@FontScalePreviews
@Composable
private fun HelloWorldPreview() {
  Text("Hello World")
}
```

## 10\. Name composable functions properly

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](https://kotlinlang.org/docs/reference/coding-conventions.html#function-names) for the naming of functions for any function annotated `@Composable` that returns a value other than `Unit`.

**DON’T DO THIS…**

1

2

```
@Composable
fun fancyButton(text: String, onClick: () -> Unit)
```

**OR THIS…**

1

2

```
@Composable
fun RenderFancyButton(text: String, onClick: () -> Unit)
```

**OR THIS…**

1

2

```
@Composable
fun drawProfileImage(image: ImageAsset)
```

**OR THIS…**

1

2

```
@Composable
fun Style(): Style
```

**INSTEAD, DO THIS…**

1

2

```
@Composable
fun FancyButton(text: String, onClick: () -> Unit)
```

**OR DO THIS…**

1

2

```
@Composable
fun BackButtonHandler(onBackPressed: () -> Unit)
```

**OR DO THIS…**

1

2

```
@Composable
fun defaultStyle(): Style
```

## 11\. Order composable parameters properly

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](https://kotlinlang.org/docs/functions.html#default-arguments).

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

```
@Composable
fun ActionButton(
  modifier: Modifier = Modifier,
  text: String,
  onButtonClick: () -> Unit = {},
)
```

**INSTEAD, DO THIS…**

1

2

3

4

5

6

```
@Composable
fun ActionButton(
  text: String,
  modifier: Modifier = Modifier,
  onButtonClick: () -> Unit = {},
)
```

## 12\. Make preview composables private

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

```
@Composable
@Preview
fun ScreenPreview()
```

**INSTEAD, DO THIS…**

1

2

3

```
@Composable
@Preview
private fun ScreenPreview()
```

## Need help with your Android app?

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](/android-developers) and [contact us](/contact) for a free consultation.

## Article Author:

[DF | Douglas Fornaro | Android Engineer](/blog/author/douglas-fornaro)

## Tags:

[Android](/tag/android) [Developer Tips](/tag/developer-tips) [Jetpack](/tag/jetpack)

## Subscribe for more insights

Get our newsletter in your inbox.

## Related posts

[12 web accessibility best practices: A starter list | ArcTouch shares 12 best practices that provide a great starting point for building accessible web experiences. | 5 min. read - April 16, 2024](/blog/web-accessibility-best-practices) [Injecting AI into software development — an ArcTouch blog series | The ArcTouch design and development team shares how to use AI to build lovable apps and websites — better and faster. | 5 min. read - April 9, 2024](/blog/ai-software-development)

## Contact us.

### Let's build something lovable. Together.

We help companies of all sizes build lovable apps, websites, and connected experiences.
