O que e Composable em Kotlin?
Uma funcao Composable e uma funcao anotada com @Composable que descreve parte da interface do usuario no Jetpack Compose, o toolkit moderno de UI declarativa do Android. Em vez de montar telas com XML e manipular Views programaticamente, voce escreve funcoes Kotlin que descrevem como a UI deve parecer para um dado estado.
O Compose e inspirado em frameworks como React e Flutter, mas aproveita todo o poder do Kotlin: type safety, extension functions, coroutines e uma sintaxe concisa que faz a construcao de interfaces parecer natural.
Sintaxe basica
import androidx.compose.runtime.Composable
import androidx.compose.material3.Text
@Composable
fun Saudacao(nome: String) {
Text(text = "Ola, $nome!")
}
A anotacao @Composable informa ao compilador do Compose que essa funcao descreve UI e pode ser recomposta (re-executada) quando os dados mudam. Funcoes Composable so podem ser chamadas dentro de outros contextos Composable.
Composicao de funcoes
O poder do Compose esta na composicao. Voce cria componentes pequenos e os combina para formar telas completas:
@Composable
fun CartaoDeUsuario(nome: String, email: String) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(
text = nome,
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = email,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
@Composable
fun ListaDeUsuarios(usuarios: List<Usuario>) {
LazyColumn {
items(usuarios) { usuario ->
CartaoDeUsuario(
nome = usuario.nome,
email = usuario.email
)
}
}
}
Cada funcao Composable e um bloco reutilizavel. CartaoDeUsuario nao sabe onde sera usado, e ListaDeUsuarios nao sabe como o cartao e renderizado internamente. Essa separacao torna o codigo modular e testavel.
Estado em Composables
Funcoes Composable sao reexecutadas quando o estado muda. Para gerenciar estado local, use remember e mutableStateOf:
@Composable
fun Contador() {
var contagem by remember { mutableStateOf(0) }
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "Contagem: $contagem")
Spacer(modifier = Modifier.height(8.dp))
Button(onClick = { contagem++ }) {
Text("Incrementar")
}
}
}
Quando contagem muda, o Compose recompoe apenas as partes da UI que dependem desse valor. Isso e feito de forma inteligente pelo runtime do Compose, que rastreia quais Composables leem quais estados.
Recomposicao
Recomposicao e o processo pelo qual o Compose reexecuta funcoes Composable quando os dados de entrada mudam. E importante entender que:
- A recomposicao pode acontecer a qualquer momento e em qualquer ordem.
- Funcoes Composable devem ser idempotentes: chamar com os mesmos parametros deve produzir o mesmo resultado.
- Funcoes Composable nao devem ter efeitos colaterais nao controlados.
// Correto: sem efeitos colaterais
@Composable
fun ExibirNome(nome: String) {
Text(text = nome)
}
// Incorreto: efeito colateral na recomposicao
@Composable
fun ExibirNomeComLog(nome: String) {
println("Recompondo...") // Pode ser chamado muitas vezes!
Text(text = nome)
}
Para efeitos colaterais controlados, use APIs como LaunchedEffect, SideEffect e DisposableEffect.
Efeitos colaterais controlados
@Composable
fun TelaDeDetalhes(userId: String) {
var usuario by remember { mutableStateOf<Usuario?>(null) }
LaunchedEffect(userId) {
// Executa quando userId muda
usuario = repositorio.buscarUsuario(userId)
}
usuario?.let { u ->
Column {
Text(text = u.nome)
Text(text = u.email)
}
}
}
LaunchedEffect lanca uma coroutine que e cancelada e reiniciada quando a chave (userId) muda. Isso garante que efeitos colaterais sejam gerenciados corretamente no ciclo de vida do Composable.
Modifiers
Modifiers sao o mecanismo do Compose para decorar e configurar componentes:
@Composable
fun CartaoEstilizado() {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.clickable { /* acao */ }
) {
Text(
text = "Conteudo do cartao",
modifier = Modifier.padding(24.dp)
)
}
}
A ordem dos modifiers importa: padding antes de clickable produz resultado diferente de clickable antes de padding.
Quando usar Composables
Composables sao usados em qualquer projeto Android que adote Jetpack Compose:
- Telas de aplicativos: construir layouts completos de forma declarativa.
- Componentes reutilizaveis: criar uma biblioteca de componentes de UI consistentes.
- Previews: usar
@Previewpara visualizar componentes no Android Studio sem rodar o app. - Testes de UI: Composables sao facilmente testaveis com a biblioteca de testes do Compose.
- Compose Multiplatform: o mesmo conceito funciona em desktop, web e iOS com Kotlin Multiplatform.
Erros comuns
Colocar logica de negocio dentro do Composable: Composables devem apenas descrever UI. Logica de negocio pertence ao ViewModel ou a camadas inferiores.
Esquecer
remember: semremember, o estado e recriado a cada recomposicao, perdendo o valor anterior.
// Errado: contagem volta a 0 a cada recomposicao
@Composable
fun ContadorQuebrado() {
var contagem = mutableStateOf(0) // Falta remember!
// ...
}
Efeitos colaterais descontrolados: fazer chamadas de rede, acessar banco de dados ou modificar estado global diretamente dentro de um Composable sem usar
LaunchedEffectou similar.Nao elevar o estado (state hoisting): manter estado em componentes filhos quando ele deveria ser controlado pelo pai. Isso dificulta reutilizacao e testes.
Ignorar a ordem dos Modifiers: como modifiers sao aplicados em cadeia, a ordem afeta o resultado visual. Testar e visualizar com
@Previewajuda a pegar esses problemas cedo.
State hoisting
Um padrao fundamental em Compose e elevar o estado para o componente pai:
// Componente stateless (sem estado proprio)
@Composable
fun CampoDeTexto(
valor: String,
onValorMudou: (String) -> Unit
) {
TextField(
value = valor,
onValueChange = onValorMudou
)
}
// Componente pai controla o estado
@Composable
fun Formulario() {
var nome by remember { mutableStateOf("") }
CampoDeTexto(
valor = nome,
onValorMudou = { nome = it }
)
}
Isso torna CampoDeTexto reutilizavel e testavel, pois ele nao gerencia seu proprio estado.
Termos relacionados
- State: o mecanismo de estado reativo que aciona recomposicoes quando valores mudam.
- Modifier: objeto que configura aparencia e comportamento de componentes Compose.
- ViewModel: gerencia estado e logica de negocio fora da camada de UI.
- LaunchedEffect: API para executar efeitos colaterais controlados dentro de Composables.
- Recomposicao: processo de reexecucao de funcoes Composable quando seus inputs mudam.
- remember: funcao que preserva estado entre recomposicoes.
Composables representam uma mudanca de paradigma na construcao de interfaces em Kotlin. Ao tratar a UI como funcao do estado, o Compose elimina toda uma classe de bugs relacionados a sincronizacao entre dados e interface, tornando o desenvolvimento mais previsivel e produtivo.