---
title: "State em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/state/"
markdown_url: "https://kotlin.dev.br/glossario/state.MD"
description: "Entenda o que é State no Jetpack Compose, como gerenciar estado reativo que aciona recomposicoes automaticas."
date: "2025-08-19"
author: "Karina Melo"
---

# State em Kotlin: O que É e Como Funciona | Kotlin Brasil

Entenda o que é State no Jetpack Compose, como gerenciar estado reativo que aciona recomposicoes automaticas.


## O que é State em Kotlin?

No contexto do Jetpack Compose, **State** (estado) é um valor que, quando muda, **aciona automaticamente a recomposicao** das funções Composable que o leem. O Compose rastreia quais Composables dependem de quais estados e reexecuta apenas os afetados quando o estado muda.

Sem estado reativo, a UI seria estática. Com State, você declara como a UI deve parecer para cada possível valor do estado, é o Compose cuida de manter tudo sincronizado.

### Criando estado com mutableStateOf

```kotlin
import androidx.compose.runtime.*

@Composable
fun Contador() {
    // Cria um estado reativo que sobrevive a recomposicoes
    var contagem by remember { mutableStateOf(0) }

    Column {
        Text(text = "Contagem: $contagem")
        Button(onClick = { contagem++ }) {
            Text("Incrementar")
        }
    }
}
```

Quando `contagem` muda (via `contagem++`), o Compose detecta a mudanca e reexecuta `Contador()`, atualizando o `Text` com o novo valor.

Tres elementos trabalham juntos:
- **`mutableStateOf(0)`**: cria um holder de estado reativo com valor inicial 0.
- **`remember`**: preserva o estado entre recomposicoes (sem `remember`, o estado seria recriado a cada vez).
- **`by`**: delegação de propriedade que permite ler e escrever o valor diretamente.

### remember vs rememberSaveable

```kotlin
@Composable
fun CampoDeTexto() {
    // remember: sobrevive a recomposicoes, mas NAO a mudancas de configuracao
    var texto by remember { mutableStateOf("") }

    // rememberSaveable: sobrevive a recomposicoes E mudancas de configuracao
    var textoSalvo by rememberSaveable { mutableStateOf("") }

    Column {
        TextField(value = texto, onValueChange = { texto = it })
        TextField(value = textoSalvo, onValueChange = { textoSalvo = it })
    }
}
```

Use `rememberSaveable` quando o estado precisa sobreviver a rotação de tela ou a recriação da Activity.

### State hoisting (elevacao de estado)

O padrão fundamental de gerenciamento de estado em Compose e **elevar o estado** para o componente pai:

```kotlin
// Componente stateless: recebe estado e eventos como parametros
@Composable
fun CampoDeNome(
    nome: String,
    onNomeMudou: (String) -> Unit,
    modifier: Modifier = Modifier
) {
    OutlinedTextField(
        value = nome,
        onValueChange = onNomeMudou,
        label = { Text("Nome") },
        modifier = modifier.fillMaxWidth()
    )
}

// Componente pai: controla o estado
@Composable
fun FormularioDeCadastro() {
    var nome by remember { mutableStateOf("") }
    var email by remember { mutableStateOf("") }

    Column(modifier = Modifier.padding(16.dp)) {
        CampoDeNome(
            nome = nome,
            onNomeMudou = { nome = it }
        )
    }
}
```

Beneficios do state hoisting:
- O componente filho e **reutilizavel** e **testavel**.
- O pai tem **controle total** sobre o estado.
- O fluxo de dados e **unidirecional**: estado desce, eventos sobem.

### derivedStateOf

Para estados que são derivados de outros estados:

```kotlin
@Composable
fun ListaComFiltro() {
    var busca by remember { mutableStateOf("") }
    val todosItens = remember { listOf("Kotlin", "Java", "Python", "Rust", "Go") }

    // Recalcula apenas quando 'busca' ou 'todosItens' mudam
    val itensFiltrados by remember(busca) {
        derivedStateOf {
            todosItens.filter { it.contains(busca, ignoreCase = true) }
        }
    }

    Column {
        TextField(value = busca, onValueChange = { busca = it })
        itensFiltrados.forEach { item ->
            Text(text = item)
        }
    }
}
```

`derivedStateOf` evita recomposicoes desnecessarias quando o calculo derivado produz o mesmo resultado.

### Estado com ViewModel

Para estado que sobrevive a mudancas de configuração e representa lógica de negócio:

```kotlin
class ListaViewModel : ViewModel() {
    private val _itens = MutableStateFlow<List<String>>(emptyList())
    val itens: StateFlow<List<String>> = _itens.asStateFlow()

    private val _carregando = MutableStateFlow(false)
    val carregando: StateFlow<Boolean> = _carregando.asStateFlow()

    fun carregar() {
        viewModelScope.launch {
            _carregando.value = true
            _itens.value = repositorio.buscarItens()
            _carregando.value = false
        }
    }
}

@Composable
fun ListaTela(viewModel: ListaViewModel = viewModel()) {
    val itens by viewModel.itens.collectAsState()
    val carregando by viewModel.carregando.collectAsState()

    if (carregando) {
        CircularProgressIndicator()
    } else {
        LazyColumn {
            items(itens) { item -> Text(text = item) }
        }
    }
}
```

`collectAsState()` converte um `StateFlow` em State do Compose, integrando o ViewModel com a recomposicao.

### Tipos de estado

```kotlin
// MutableState: estado simples do Compose
val estado: MutableState<Int> = mutableStateOf(0)

// StateFlow: estado observavel de coroutines
val fluxo: StateFlow<Int> = MutableStateFlow(0)

// LiveData: estado observavel do Android (legado)
val liveData: LiveData<Int> = MutableLiveData(0)

// Todos podem ser convertidos para State do Compose:
val a by remember { mutableStateOf(0) }
val b by fluxo.collectAsState()
val c by liveData.observeAsState(0)
```

### snapshotFlow: State para Flow

Para observar mudancas de State como um Flow:

```kotlin
@Composable
fun BuscaComDebounce() {
    var query by remember { mutableStateOf("") }

    LaunchedEffect(Unit) {
        snapshotFlow { query }
            .debounce(300)
            .distinctUntilChanged()
            .collect { busca ->
                // Executar busca apos 300ms sem digitacao
                buscar(busca)
            }
    }

    TextField(value = query, onValueChange = { query = it })
}
```

### Quando usar cada tipo de estado

| Tipo | Uso | Escopo |
|---|---|---|
| `remember + mutableStateOf` | Estado de UI local | Composable |
| `rememberSaveable` | Estado que sobrevive rotação | Composable |
| `derivedStateOf` | Estado calculado de outros estados | Composable |
| `ViewModel + StateFlow` | Logica de negócio e dados | Tela |
| `snapshotFlow` | Converter State em Flow | Bridge |

### Casos de Uso no Mundo Real

1. **Formularios reativos**: em telas de cadastro, login ou checkout, cada campo (nome, email, senha, endereco) e representado por um `mutableStateOf`. Mudancas no texto atualizam o estado, que por sua vez aciona recomposicao dos componentes visuais, incluindo validacao em tempo real e habilitacao/desabilitacao do botao de envio.

2. **Telas com carregamento e paginação**: aplicações que consomem APIs usam `StateFlow` no ViewModel para representar estados como carregando, sucesso, erro e lista vazia. O Composable coleta esse fluxo com `collectAsState()` e renderiza a UI apropriada para cada estado, incluindo indicadores de progresso e mensagens de erro.

3. **Temas e preferencias do usuário**: aplicações que permitem alternar entre tema claro e escuro ou alterar tamanho de fonte usam estado global (geralmente via `CompositionLocal` ou ViewModel compartilhado) para propagar mudancas de configuração por toda a arvore de Composables, recompondo apenas os componentes afetados.

4. **Jogos e animacoes interativas**: aplicações que exibem animacoes baseadas em interação do usuário (arrastar, pincar, rotacionar) usam `mutableStateOf` combinado com `Animatable` para rastrear posicao, escala e rotação de elementos visuais, com recomposicao automatica a cada frame de animacao.

### Boas Praticas

- **Eleve o estado (state hoisting) sempre que um componente pai precisar controlar ou observar o valor**: mantenha componentes filhos stateless, recebendo estado e callbacks como parametros. Isso torna os componentes reutilizaveis, testáveis e com fluxo de dados previsivel.
- **Use `derivedStateOf` para calculos derivados de outros estados**: em vez de recompor toda vez que um estado base muda, `derivedStateOf` recalcula o valor derivado apenas quando necessário e só aciona recomposicao se o resultado realmente mudar.
- **Separe estado de UI de estado de negócio**: estado de UI local (como se um dropdown esta aberto) deve ficar no Composable com `remember`. Estado de negócio (como a lista de itens carregados do servidor) deve ficar no ViewModel com `StateFlow`.
- **Nunca mute colecoes dentro de `mutableStateOf` diretamente**: o Compose detecta mudancas por referência. Alterar o conteudo de uma `MutableList` sem criar uma nova instancia não aciona recomposicao. Sempre crie uma nova colecao ao modificar.
- **Prefira `rememberSaveable` para estado que precisa sobreviver a rotação de tela**: `remember` perde o valor quando a Activity e recriada. Para dados como texto digitado pelo usuário, use `rememberSaveable` para preservar o estado automaticamente.

### Perguntas Frequentes

**P: Qual a diferenca entre `mutableStateOf` e `MutableStateFlow`?**
R: `mutableStateOf` e a primitiva de estado do Compose, integrada diretamente ao sistema de recomposicao. `MutableStateFlow` e uma primitiva de coroutines que representa um fluxo de estado. No ViewModel, prefira `StateFlow` para expor estado (pois o ViewModel não deve depender do Compose). No Composable, converta para State com `collectAsState()`.

**P: Quando devo usar `remember` vs `rememberSaveable` vs ViewModel?**
R: Use `remember` para estado de UI efemero que não precisa sobreviver a rotação (ex: se um tooltip esta visivel). Use `rememberSaveable` para estado de UI que deve sobreviver a mudancas de configuração (ex: texto digitado em um campo). Use ViewModel para estado de negócio e dados carregados de APIs ou banco de dados.

**P: Por que meu Composable não recompoe quando mudo o estado?**
R: As causas mais comuns sao: (1) esqueceu de usar `remember`, entao o estado e recriado a cada recomposicao; (2) esta mutando uma colecao existente em vez de criar uma nova; (3) o valor sendo comparado e estruturalmente igual ao anterior, entao o Compose não detecta mudanca; (4) o estado esta sendo lido fora do escopo de composicao (ex: em um `LaunchedEffect` sem dependência correta).

**P: E seguro acessar `mutableStateOf` de várias threads?**
R: As leituras e escritas individuais em `mutableStateOf` sao thread-safe. Porem, operações compostas (ler e escrever baseado no valor lido) não sao atomicas. Para esses casos, use `Snapshot.withMutableSnapshot` ou gerencie a concorrencia no ViewModel com coroutines.

### Erros comuns

1. **Esquecer `remember`**: sem `remember`, o estado e recriado a cada recomposicao, perdendo o valor.

```kotlin
// ERRADO
@Composable
fun Quebrado() {
    var x = mutableStateOf(0) // Recriado toda recomposicao!
}

// CORRETO
@Composable
fun Correto() {
    var x by remember { mutableStateOf(0) }
}
```

2. **Colocar lógica de negócio no Composable**: buscar dados, processar regras de negócio e acessar banco de dados devem ficar no ViewModel, não no Composable.

3. **Nao elevar estado quando necessário**: manter estado em componentes filhos quando o pai precisa controla-lo dificulta a comunicação e reutilização.

4. **mutação direta de coleções**: mudar o conteudo de uma `MutableList` dentro de um `mutableStateOf` não aciona recomposicao. Você precisa criar uma nova lista.

```kotlin
// ERRADO: nao aciona recomposicao
val lista = remember { mutableStateOf(mutableListOf(1, 2, 3)) }
lista.value.add(4) // Compose nao detecta!

// CORRETO: cria nova lista
val lista = remember { mutableStateOf(listOf(1, 2, 3)) }
lista.value = lista.value + 4 // Nova referência, Compose detecta
```

5. **Usar `remember` para estado que precisa sobreviver a rotação**: `remember` não sobrevive a mudancas de configuração. Use `rememberSaveable` ou ViewModel.

### Termos relacionados

- **Composable**: função que lê State e e recomposta quando o estado muda.
- **Recomposicao**: reexecucao de funções Composable quando seus estados de entrada mudam.
- **ViewModel**: gerencia estado e lógica de negócio fora da camada de UI.
- **StateFlow**: fluxo de estado de coroutines que pode ser convertido em State do Compose.
- **remember**: função que preserva valores entre recomposicoes.
- **Flow**: stream reativo que pode ser coletado como State usando `collectAsState`.

State e o conceito central do Jetpack Compose. Entender como criar, elevar, derivar e gerenciar estado e o que separa interfaces reativas e corretas de interfaces com bugs de sincronizacao. O modelo declarativo do Compose torna o gerenciamento de estado mais previsivel e menos propenso a erros do que a abordagem imperativa tradicional.
