Jetpack Compose é um toolkit declarativo moderno para construir interfaces Android em Kotlin. O desenvolvedor descreve a UI através de funções composable, e o toolkit redesenha automaticamente apenas as partes que mudaram. De acordo com Android Developers (2026), o Jetpack Compose funciona no Android 5.0 (API 21) e superior, suporta Material Design 3 e atinge 120 FPS em dispositivos de gama média graças ao seu próprio sistema de Recomposition — um algoritmo diff inteligente que atualiza apenas os widgets que mudaram.
Principais pontos
Jetpack Compose é um framework declarativo do Google para construir interfaces de usuário Android, anunciado em 2019 e que atingiu o lançamento estável em 2021. Ao contrário do antigo View System (layout XML + Activity/Fragment), o Compose usa funções Kotlin anotadas — @Composable. A interface é descrita inteiramente em Kotlin: não há separação entre XML e código. Isso eliminou a classe de erros relacionados a IDs incompatíveis em XML e Kotlin (o type-safe synthetic não ajudava na refatoração).
O Compose é construído em seu próprio sistema de renderização — Canvas, não vinculado à hierarquia de View. Cada Composable se desenha diretamente no Canvas, ignorando onMeasure/onDraw do View System. Isso proporciona um ganho de desempenho em telas complexas: nos testes do Google (2023), uma tela em Compose com 200 elementos foi renderizada 40% mais rápido que uma similar em RecyclerView + ViewHolder.
O Compose requer minSdk 21 (Android 5.0) e Kotlin 1.9+. O BOM (Bill of Materials) do Compose sincroniza as versões de todas as bibliotecas do Compose. O framework é compatível com código existente do View System: o Compose é incorporado via ComposeView em layouts XML, e Views antigas via AndroidView na hierarquia do Compose. De acordo com o Google Play Console (2025), o Android 5.0+ cobre 97% dos dispositivos ativos, portanto a compatibilidade não é uma limitação para a maioria dos projetos.
@Composable é uma anotação que transforma uma função Kotlin comum em um bloco de construção de UI. Uma função Composable descreve como um fragmento da interface deve parecer — texto, botão, lista. Em vez de retornar um valor, a função emite componentes UI na composição. É semelhante a um gerador: cada função adiciona elementos à tela quando chamada.
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
Card(
modifier = Modifier.fillMaxWidth().padding(16.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface
)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage(
model = avatarUrl,
contentDescription = "Avatar",
modifier = Modifier.size(48.dp).clip(CircleShape)
)
Spacer(Modifier.width(12.dp))
Text(
text = name,
style = MaterialTheme.typography.titleMedium
)
}
}
}
A função ProfileCard recebe parâmetros (name, avatarUrl) e emite Card → Row → AsyncImage + Text. Composição é a árvore de componentes emitidos em uma única passagem. Se os parâmetros não mudaram, o Compose pula a chamada da função (recomposition skip). Se apenas name mudou, apenas Text será chamado, os demais elementos não serão redesenhados. Essa recomposição inteligente é a principal vantagem de desempenho do Compose sobre a otimização manual do View System.
As funções Composable usam ativamente slots — trailing lambda, content: @Composable (() -> Unit). Isso permite criar contêineres: Card, Column, Row aceitam uma lambda content, e o conteúdo é inserido no slot. A Slot API substituiu atributos XML como android:layout_gravity — agora o posicionamento dos elementos filhos é definido por código Kotlin dentro do bloco de conteúdo.
State no Compose é qualquer valor que pode mudar ao longo do tempo. Quando o estado muda, o Compose agenda a recomposição para todos os componentes que leem esse estado. O mecanismo se assemelha aos hooks do React: mutableStateOf retorna MutableState<T>, a leitura de .value inscreve automaticamente a composição atual nas mudanças.
@Composable
fun CounterExample() {
var count by remember { mutableStateOf(0) }
Column(modifier = Modifier.padding(16.dp)) {
Text("Clicado: $count")
Button(onClick = { count++ }) {
Text("Incrementar")
}
}
}
@Composable
fun UserScreen(viewModel: UserViewModel) {
val userName by viewModel.userName.collectAsState()
Text("Usuário: $userName")
}
remember preserva o valor entre recomposições — caso contrário, mutableStateOf seria criado novamente a cada atualização de UI. collectAsState() converte StateFlow da ViewModel em um estado compatível com Compose. Recomendação — use ViewModel com StateFlow para estado no nível de tela, e mutableStateOf para estado local (por exemplo, cartão expandido). Essa separação segue o princípio de componentes inteligentes/mudos.
State Hoisting é um padrão de elevação do estado de um componente filho para o pai. O pai passa o valor e um callback através de parâmetros, o filho chama o callback ao mudar. O pai mantém o mutableStateOf, o filho apenas os parâmetros. Isso torna o componente reutilizável e testável: o mesmo TextField pode ser usado com qualquer fonte de dados.
Modifier é um objeto que descreve transformações do Composable: tamanho, padding, fundo, manipulação de cliques, animação, rolagem. Os modificadores são aplicados através de uma cadeia de chamadas: Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }. Cada chamada retorna um novo Modifier com a propriedade adicionada — sem mutação do objeto original.
A ordem dos modificadores é importante. Modifier.padding(16.dp).background(Color.Blue) preenche a área com padding. Modifier.background(Color.Blue).padding(16.dp) preenche o retângulo interno, e o padding permanece transparente. A mecânica se assemelha ao modelo de caixa CSS: padding primeiro → background funciona como margin + background; background primeiro → padding funciona como background + padding interno. O desenvolvedor só precisa lembrar: padding primeiro = margem externa, padding depois = padding interno.
Se os modificadores integrados não forem suficientes, cria-se um personalizado via Modifier.composed { ... } ou Modifier.then(). Dentro de um modificador personalizado, pode-se usar medições de layout (Modifier.layout { measurable, constraints -> ... }), desenho (Modifier.drawWithContent { ... }), gestos (Modifier.pointerInput { ... }). Exemplo: um modificador para animação pulsante ao clicar — mede o tamanho, ao clicar inicia uma animação de escala via animateFloatAsState.
Para animações, o Compose fornece animate*AsState (animateFloatAsState, animateColorAsState, animateDpAsState) — os valores animam entre o estado antigo e o novo ao mudar. Para animações de entrada/saída — AnimatedVisibility e AnimatedContent com transições integradas (fade, slide, expand). Todas as animações funcionam na camada gráfica sem desencadear composição desnecessária.
As funções Composable não devem realizar efeitos colaterais diretamente (requisições de rede, temporizadores, assinaturas) — elas são chamadas em cada recomposição, o que levaria a requisições duplicadas. Para efeitos colaterais, o Compose fornece uma família de funções Effect: LaunchedEffect inicia uma corrotina ao entrar na composição e a cancela ao sair, DisposableEffect — para recursos que exigem limpeza explícita (sensores, BroadcastReceiver).
@Composable
fun SensorReader() {
val context = LocalContext.current
var sensorValue by remember { mutableStateOf(0f) }
DisposableEffect(Unit) {
val sensor = registerSensorListener(context) { value ->
sensorValue = value
}
onDispose {
unregisterSensorListener(sensor)
}
}
Text("Valor: $sensorValue")
}
@Composable
fun UserGreeting(userId: String) {
LaunchedEffect(userId) {
val profile = api.fetchProfile(userId)
// atualização de estado
}
}
LaunchedEffect(userId) reinicia se o userId mudar — a corrotina anterior é cancelada e uma nova é iniciada com o novo userId. Isso elimina o gerenciamento manual de cancelamento de requisições. DisposableEffect(Unit) — um efeito com chave fixa Unit, dispara ao entrar na composição e chama onDispose ao sair. SensorReader registra um listener e cancela a assinatura ao sair da tela — sem risco de vazamentos.
Se for necessário iniciar uma corrotina não ao entrar na composição mas sim em um evento (clique em botão), usa-se rememberCoroutineScope(). Ele retorna um CoroutineScope vinculado ao ciclo de vida do Composable, sem necessidade de DisposableEffect. Exemplo: iniciar uma requisição de rede ao clicar em um botão — scope.launch { viewModel.loadData() }.
Escolher entre Compose e View System é a principal questão arquitetônica para desenvolvedores Android em 2026. Ambas as tecnologias são suportadas pelo Google, mas o Compose é a direção principal na qual o Google investe recursos. O View System recebe apenas correções críticas e não evolui. A diferença se manifesta na sintaxe, gerenciamento de estado, desempenho e tempo de desenvolvimento.
| Aspecto | Jetpack Compose | View System |
|---|---|---|
| Descrição da UI | Funções Kotlin @Composable | Layout XML + Activity/Fragment |
| Estado | mutableStateOf, StateFlow, redesenho automático | findViewById, manual: setText, notifyDataSetChanged |
| Desempenho | Recomposição inteligente, renderização Canvas | Hierarquia de View, measure/layout/draw |
| Animações | animate*AsState, AnimatedVisibility, integradas | ValueAnimator, ObjectAnimator, Transition |
| Compatibilidade | minSdk 21, pontes ComposeView/AndroidView | Todas as versões, qualquer |
| Tamanho APK | +3–5 MB para Compose | Sem sobrecarga |
Para novos projetos, o Google recomenda o Jetpack Compose como padrão para desenvolvimento de UI. O View System permanece para manter código escrito antes de 2021, e para casos onde o tamanho mínimo do APK é crítico (por exemplo, para mercados emergentes com dispositivos de entrada). Compose reduz o volume de código UI em 30–50% em comparação com o View System graças à sua sintaxe declarativa e animações integradas.
Perguntas frequentes
Sim, através de ComposeView no layout XML. Adicione a dependência do Compose e envolva a tela ou parte dela em ComposeView { MyComposable() }. A migração é tela por tela.
A razão é que o estado está elevado muito alto ou objetos mutáveis estão sendo usados. Correção: derivedStateOf para dados derivados e remember para referências estáveis.
Use LazyColumn (análogo ao RecyclerView). Os elementos são criados e reutilizados conforme a rolagem. Para listas complexas com diferentes tipos de células — LazyColumn { items(items, key = { it.id }) { ... } }.
Não, você pode começar diretamente com Compose. O conhecimento de View System ajuda na manutenção de código legado, mas Compose é um ecossistema independente com sua própria documentação e padrões.
Sim, Material 3 é o tema padrão do Compose desde 2023. É adicionado via implementation("androidx.compose.material3:material3"). Material 2 é considerado obsoleto.
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