In Compose the UI is immutable---there's no way to update it after it's been drawn. What you can control is the state of your UI. Every time the state of the UI changes, Compose[recreates the parts of the UI tree that have changed](https://developer.android.com/develop/ui/compose/mental-model#recomposition). Composables can accept state and expose events---for example, a`TextField`accepts a value and exposes a callback`onValueChange`that requests the callback handler to change the value.

<br />

```kotlin
var name by remember { mutableStateOf("") }
OutlinedTextField(
    value = name,
    onValueChange = { name = it },
    label = { Text("Name") }
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/architecture/ArchitectureSnippets.kt#L47-L52
```

<br />

Because composables accept state and expose events, the unidirectional data flow pattern fits well with Jetpack Compose. This guide focuses on how to implement the unidirectional data flow pattern in Compose, how to implement events and state holders, and how to work with ViewModels in Compose.
| **Note:** The other layers of your app---the data layer and the business layer---are not affected by adopting Jetpack Compose. To learn more about architecting all layers of your app, check out the[guide to app architecture](https://developer.android.com/jetpack/guide).

## Unidirectional data flow

A*unidirectional data flow*(UDF) is a design pattern where state flows down and events flow up. By following unidirectional data flow, you can decouple composables that display state in the UI from the parts of your app that store and change state.

The UI update loop for an app using unidirectional data flow looks like this:

1. **Event**: Part of the UI generates an event and passes it upward, such as a button click passed to the ViewModel to handle; or an event is passed from other layers of your app, such as indicating that the user session has expired.
2. **Update state**: An event handler might change the state.
3. **Display state**: The state holder passes down the state, and the UI displays it.

![Events flow up from the UI to a state holder, and state flows down from the state holder to the UI.](https://developer.android.com/static/develop/ui/compose/images/state-unidirectional-flow.png)**Figure 1.**Unidirectional data flow.

Following this pattern when using Jetpack Compose provides several advantages:

- **Testability**: Decoupling state from the UI that displays it makes it easier to test both in isolation.
- **State encapsulation**: Because state can only be updated in one place and there is only one source of truth for the state of a composable, it's less likely that you'll create bugs due to inconsistent states.
- **UI consistency** : All state updates are immediately reflected in the UI by the use of observable state holders, like`StateFlow`or`LiveData`.

### Unidirectional data flow in Jetpack Compose

Composables work based on state and events. For example, a`TextField`is only updated when its`value`parameter is updated and it exposes an`onValueChange`callback---an event that requests the value to be changed to a new one. Compose defines the`State`object as a value holder, and changes to the state value trigger a recomposition. You can hold the state in a`remember { mutableStateOf(value) }`or a`rememberSaveable { mutableStateOf(value)`depending on how long you need to remember the value for.

The type of the`TextField`composable's value is`String`, so this can come from anywhere---from a hardcoded value, from a ViewModel, or passed in from the parent composable. You don't have to hold it in a`State`object, but you need to update the value when`onValueChange`is called.
| **Key Point:** `mutableStateOf(value)`creates a`MutableState`, which is an observable type in Compose. Any changes to its value schedule recomposition of any composable functions that read that value.`remember`stores objects in the composition, and forgets the object when the composable that called`remember`is removed from the composition.`rememberSaveable`retains the state across configuration changes by saving it in a`Bundle`.
| **Note:** To learn more about state and state hoisting in Compose, see[State and Jetpack Compose](https://developer.android.com/develop/ui/compose/state).

### Define composable parameters

When defining the state parameters of a composable, keep the following questions in mind:

- How reusable or flexible is the composable?
- How do the state parameters affect this composable's performance?

To promote decoupling and reuse, each composable should hold the least amount of information possible. For example, when building a composable to hold the header of a news article, prefer passing in only the information that needs to be displayed, rather than the entire news article:

<br />

```kotlin
@Composable
fun Header(title: String, subtitle: String) {
    // Recomposes when title or subtitle have changed.
}

@Composable
fun Header(news: News) {
    // Recomposes when a new instance of News is passed in.
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/architecture/ArchitectureSnippets.kt#L60-L68
```

<br />

Sometimes, using individual parameters also improves performance---for example, if`News`contains more information than just`title`and`subtitle`, whenever a new instance of`News`is passed into`Header(news)`, the composable will recompose, even if`title`and`subtitle`haven't changed.

Consider carefully the number of parameters you pass in. Having a function with too many parameters decreases the ergonomics of the function, so in this case grouping them up in a class is preferred.

## Events in Compose

Every input to your app should be represented as an event: taps, text changes, and even timers or other updates. As these events change the state of your UI, the`ViewModel`should handle them and update the UI state.

The UI layer should never change state outside of an event handler because this can introduce inconsistencies and bugs in your application.

Prefer passing immutable values for state and event handler lambdas. This approach has the following benefits:

- You improve reusability.
- You verify that your UI doesn't change the value of the state directly.
- You avoid concurrency issues because you make sure that the state isn't mutated from another thread.
- Often, you reduce code complexity.

For example, a composable that accepts a`String`and a lambda as parameters can be called from many contexts and is highly reusable. Suppose that the top app bar in your app always displays text and has a back button. You can define a more generic`MyAppTopAppBar`composable that receives the text and the back button handle as parameters:

<br />

```kotlin
@Composable
fun MyAppTopAppBar(topAppBarText: String, onBackPressed: () -> Unit) {
    TopAppBar(
        title = {
            Text(
                text = topAppBarText,
                textAlign = TextAlign.Center,
                modifier = Modifier
                    .fillMaxSize()
                    .wrapContentSize(Alignment.Center)
            )
        },
        navigationIcon = {
            IconButton(onClick = onBackPressed) {
                Icon(
                    Icons.AutoMirrored.Filled.ArrowBack,
                    contentDescription = localizedString
                )
            }
        },
        // ...
    )
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/architecture/ArchitectureSnippets.kt#L76-L98
```

<br />

### ViewModels, states, and events: an example

By using`ViewModel`and`mutableStateOf`, you can also introduce unidirectional data flow in your app if one of the following is true:

- The state of your UI is exposed using observable state holders, like`StateFlow`or`LiveData`.
- The`ViewModel`handles events coming from the UI or other layers of your app and updates the state holder based on the events.

For example, when implementing a sign-in screen, tapping on a**Sign in**button should cause your app to display a progress spinner and a network call. If the login was successful, then your app navigates to a different screen; in case of an error the app shows a Snackbar. Here's how you would model the screen state and the event:

The screen has four states:

- **Signed out**: when the user has not signed in yet.
- **In progress**: when your app is trying to sign the user in by performing a network call.
- **Error**: when an error occurred while signing in.
- **Signed in**: when the user is signed in.

You can model these states as a sealed class. The`ViewModel`exposes the state as a`State`, sets the initial state, and updates the state as needed. The`ViewModel`also handles the sign-in event by exposing an`onSignIn()`method.

<br />

```kotlin
class MyViewModel : ViewModel() {
    private val _uiState = mutableStateOf<UiState>(UiState.SignedOut)
    val uiState: State<UiState>
        get() = _uiState

    // ...
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/architecture/ArchitectureSnippets.kt#L111-L118
```

<br />

In addition to the`mutableStateOf`API, Compose[provides extensions](https://developer.android.com/develop/ui/compose/interop#streams)for`LiveData`,`Flow`, and`Observable`to register as a listener and represent the value as a state.

<br />

```kotlin
class MyViewModel : ViewModel() {
    private val _uiState = MutableLiveData<UiState>(UiState.SignedOut)
    val uiState: LiveData<UiState>
        get() = _uiState

    // ...
}

@Composable
fun MyComposable(viewModel: MyViewModel) {
    val uiState = viewModel.uiState.observeAsState()
    // ...
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/architecture/ArchitectureSnippets.kt#L124-L136
```

<br />

## Learn more

To learn more about architecture in Jetpack Compose, consult the following resources:

### Samples

## Recommended for you

- Note: link text is displayed when JavaScript is off
- [State and Jetpack Compose](https://developer.android.com/develop/ui/compose/state)
- [Save UI state in Compose](https://developer.android.com/develop/ui/compose/state-saving)
- [Handle user input](https://developer.android.com/develop/ui/compose/text/user-input)