remember é uma função no Jetpack Compose que permite preservar um valor entre recomposições, evitando a redefinição de estado em cada reinicialização de uma função Composable. Sem remember, todas as variáveis declaradas dentro de uma função seriam redefinidas em cada atualização de UI, tornando o estado instável e inútil. De acordo com Google Android Developers, 2026, o uso correto de remember é a base do gerenciamento adequado de estado em UI declarativa.
Pontos Principais
remember é uma função integrada do Jetpack Compose do pacote androidx.compose.runtime que cria um objeto preservando seu valor entre chamadas sucessivas de uma função Composable. Tecnicamente, remember trabalha com slots — células especiais de memória alocadas para cada posição de chamada de função na árvore de UI. Enquanto a função permanecer na composição (não removida por uma condição if), remember retornará o valor salvo em cada recomposição.
A sintaxe de remember é simples: dentro de chaves, especifica-se o bloco de cálculo do valor inicial. O bloco é executado apenas uma vez — durante a primeira composição da função. Todas as recomposições subsequentes retornam o valor já salvo sem reexecutar o bloco. No entanto, se um parâmetro chave for especificado, o bloco é reexecutado quando a chave muda, permitindo recalcular o valor com base nos dados de entrada.
remember não é mágica do Kotlin — é uma função simples com um parâmetro chave e uma lambda de cálculo. Sua implementação interna usa Composer para ler e escrever nos slots. O compilador Kotlin, ao ver uma chamada remember, gera código que acessa o CompositionContext atual e gerencia os slots. Isso significa que remember só pode ser chamado dentro de uma função Composable ou outra função no contexto de composição.
No Jetpack Compose, existem três variantes principais de remember, cada uma com seu propósito. O remember básico preserva o valor apenas na memória do processo atual — na rotação da tela (config change), o Compose recria a Composition e todos os valores de remember são redefinidos. Para preservar dados durante mudanças de configuração e parada do processo, usa-se rememberSaveable.
rememberSaveable serializa o valor em um Bundle através do mecanismo SavedStateHandle ou Parcelable. Isso permite sobreviver à rotação da tela, à configuração "Não manter atividades" e até mesmo à minimização temporária do aplicativo. No entanto, rememberSaveable impõe restrições ao tipo de dados que pode armazenar: eles devem ser primitivos, Parcelable, Serializable ou suportar um conversor Saver.
derivedStateOf não é um mecanismo de preservação, mas uma otimização. Cria um State cujo valor é calculado a partir de outros objetos State. derivedStateOf reage a mudanças nos estados fonte, mas recalcula o valor apenas quando há assinantes. Se a recomposição atual não lê o derivedStateOf, o cálculo não é realizado, economizando recursos em atualizações frequentes mas desnecessárias.
@Composable
fun RememberVariants() {
// 1. Remember básico: persiste até sair da composição
val createdAt = remember { System.currentTimeMillis() }
// 2. rememberSaveable: sobrevive à rotação da tela
var username by rememberSaveable { mutableStateOf("") }
// 3. derivedStateOf: calculado apenas quando necessário
val isButtonVisible = remember {
derivedStateOf { username.length() > 3 }
}
Text("Criado: $createdAt")
TextField(value = username, onValueChange = { username = it })
if (isButtonVisible.value) {
Text("O botão será mostrado")
}
}
A escolha entre remember e rememberSaveable depende de quão crítico é preservar os dados durante mudanças de configuração. Para estados temporários que não são importantes perder na rotação (animação, posição atual de rolagem, estado de foco) — remember comum é suficiente. Para dados críticos (texto em formulários, itens selecionados, caixas de seleção) — use rememberSaveable.
Desempenho: rememberSaveable é mais lento que remember comum porque requer serialização em um Bundle. Use rememberSaveable apenas para dados que realmente precisam sobreviver à recriação da Activity. Para todo o resto — remember simples. O uso excessivo de rememberSaveable causa lentidão na rotação da tela e ao alternar entre aplicativos.
Se você trabalha com classes que não suportam Parcelable ou Serializable, use Saver — um conversor que define como salvar e restaurar o objeto. Saver é descrito por um par de lambdas: save (converte o objeto para um tipo armazenável) e restore (restaura o objeto a partir dos dados salvos). Um Saver padrão já está implementado para mutableStateListOf e mutableStateMapOf.
| Característica | remember | rememberSaveable |
|---|---|---|
| Preservação durante recomposição | Sim | Sim |
| Preservação na rotação | Não | Sim |
| Preservação na parada do processo | Não | Sim |
| Requisitos de tipo | Qualquer | Parcelable, Serializable, Saver |
| Desempenho | Alto | Médio |
Considere um cenário típico — uma tela de edição de perfil onde remember é usado para vários propósitos: armazenar estado dos campos do formulário, calcular valores derivados e armazenar em cache operações computacionalmente caras.
data class ProfileUiState(
val name: String = "",
val bio: String = "",
val isSaving: Boolean = false
)
@Composable
fun ProfileEditor() {
var state by rememberSaveable { mutableStateOf(ProfileUiState()) }
val isValid = remember {
derivedStateOf { state.name.isNotBlank() && state.bio.length() <= 500 }
}
val bioWarning = remember(state.bio) {
if (state.bio.length() > 400) {
"${500 - state.bio.length} chars left"
} else null
}
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = state.name,
onValueChange = { state = state.copy(name = it) },
label = { Text("Nome") }
)
OutlinedTextField(
value = state.bio,
onValueChange = { state = state.copy(bio = it) },
label = { Text("Sobre") }
)
bioWarning?.let { Text(it, color = MaterialTheme.colorScheme.error) }
Button(onClick = { /* save */ },
enabled = isValid.value) {
Text("Salvar")
}
}
}
No exemplo, o estado é salvo via rememberSaveable — o texto não será perdido na rotação da tela. isValid é calculado via derivedStateOf, o que evita cálculos desnecessários durante as recomposições. bioWarning usa remember com a chave bio — este é um cálculo caro (opcional, para demonstração) que recalcula apenas quando bio muda, não em cada recomposição.
Estados derivados são valores calculados a partir de outros objetos State. Em vez de calculá-los em cada recomposição e desperdiçar CPU em resultados idênticos, remember com derivedStateOf calcula o valor apenas quando as fontes mudam. Isso é especialmente útil para filtragem, ordenação e agregação de dados.
remember com chaves (remember(key) { calculation }) é outro mecanismo de otimização. Se a chave não mudou desde a última recomposição, o bloco de cálculo não é executado e o valor em cache é retornado. Isso é conveniente para armazenar em cache objetos cuja criação é cara: formatação de datas, análise JSON, criação de grandes coleções imutáveis.
@Composable
fun SearchResults(allItems: List<Item>, query: String) {
// derivedStateOf: filtro recalculado apenas quando as entradas mudam
val filtered = remember {
derivedStateOf {
allItems.filter { it.title.contains(query, true) }
}
}
// remember com chave: estatísticas formatadas recalculadas apenas na mudança da consulta
val statsText = remember(query) {
"Results for query \"$query\": ${filtered.value.size}"
}
Text(statsText)
LazyColumn {
items(filtered.value, key = { it.id }) { item ->
Text(item.title)
}
}
}
filtered é um derivedStateOf que recalcula automaticamente quando allItems ou query mudam. statsText usa remember(query) — a formatação cara de strings é realizada apenas quando a consulta de pesquisa muda. A combinação de derivedStateOf e remember com chaves proporciona o máximo desempenho: o estado derivado é calculado apenas quando necessário e objetos complexos são armazenados em cache até a chave mudar.
Perguntas Frequentes
Não, remember é uma função do pacote compose.runtime que requer um CompositionContext. Só pode ser chamada dentro de uma função @Composable ou dentro de outra função chamada de uma Composable. Para armazenar dados fora da composição, use ViewModel.
Sem uma chave, remember executa o bloco de cálculo apenas uma vez — durante a primeira composição. Todas as recomposições subsequentes retornam o valor salvo. Se precisar recalcular o valor quando os dados mudam, certifique-se de especificá-los como chave: remember(data) { compute(data) }.
Não há uma maneira direta de redefinir remember. A única maneira é remover a função da composição (por exemplo, escondendo-a com uma condição if) e depois mostrá-la novamente. Ao reentrar, o bloco remember é executado novamente, criando um novo valor inicial.
remember armazena estado em um slot de função Composable e vive enquanto a função estiver em composição. ViewModel vive enquanto durar o ciclo de vida da tela. ViewModel é preservado na rotação e usado para lógica de negócio. remember é para estado local de UI que não é necessário fora de uma única função.
Sim, remember funciona corretamente em funções @Preview Composable porque Preview cria um CompositionContext completo. No entanto, rememberSaveable pode não funcionar corretamente no Preview porque SavedStateHandle pode estar ausente no ambiente de prévia.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também