Se você quer desenvolver apps Android em 2026, Kotlin é o caminho. Desde 2019, o Google recomenda Kotlin como linguagem principal para Android, e hoje praticamente toda a documentação oficial e novos recursos são pensados primeiro em Kotlin. Vamos ver como começar.
Por que Kotlin para Android?
Não é exagero dizer que Kotlin revolucionou o desenvolvimento Android. Antes, a gente escrevia toneladas de boilerplate em Java, lidava com NullPointerException a todo momento e sofria com callbacks aninhados. Kotlin resolveu tudo isso de uma vez.
Os principais benefícios para Android:
- Jetpack Compose: o toolkit moderno de UI do Android é escrito em Kotlin
- Coroutines: substituem AsyncTask e callbacks complexos
- Null Safety: menos crashes em produção
- Código conciso: menos linhas, menos bugs, mais clareza
- Interop com Java: seu código legado continua funcionando
Configurando o ambiente
Para começar, você precisa do Android Studio (que já vem com suporte nativo a Kotlin). Ao criar um novo projeto, selecione Kotlin como linguagem — simples assim.
No build.gradle.kts do seu módulo app, as dependências básicas ficam assim:
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
}
android {
namespace = "br.dev.kotlin.meuapp"
compileSdk = 35
defaultConfig {
applicationId = "br.dev.kotlin.meuapp"
minSdk = 24
targetSdk = 35
}
}
dependencies {
implementation(platform("androidx.compose:compose-bom:2025.12.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.activity:activity-compose:1.9.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0")
}
Jetpack Compose: UI moderna com Kotlin
Jetpack Compose mudou completamente a forma de construir interfaces no Android. Esqueça XML — agora tudo é código Kotlin declarativo.
@Composable
fun TelaDeBoasVindas(nome: String) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Fala, $nome!",
style = MaterialTheme.typography.headlineLarge
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Bem-vindo ao app Kotlin Brasil",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(32.dp))
Button(onClick = { /* ação aqui */ }) {
Text("Começar")
}
}
}
Repare como é intuitivo: você compõe a tela usando funções. Cada @Composable é um bloco de construção reutilizável.
Gerenciamento de estado
No Compose, estado é tudo. Quando o estado muda, a UI recompõe automaticamente:
@Composable
fun ContadorSimples() {
var contagem by remember { mutableIntStateOf(0) }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(16.dp)
) {
Text(
text = "Contagem: $contagem",
style = MaterialTheme.typography.displayMedium
)
Spacer(modifier = Modifier.height(16.dp))
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = { contagem-- }) {
Text("-")
}
Button(onClick = { contagem++ }) {
Text("+")
}
}
}
}
ViewModel com Kotlin
Para estado mais complexo, usamos ViewModel com StateFlow:
data class ListaDeTarefasUiState(
val tarefas: List<String> = emptyList(),
val carregando: Boolean = false
)
class TarefasViewModel : ViewModel() {
private val _uiState = MutableStateFlow(ListaDeTarefasUiState())
val uiState: StateFlow<ListaDeTarefasUiState> = _uiState.asStateFlow()
fun adicionarTarefa(tarefa: String) {
_uiState.update { estadoAtual ->
estadoAtual.copy(
tarefas = estadoAtual.tarefas + tarefa
)
}
}
fun carregarTarefas() {
viewModelScope.launch {
_uiState.update { it.copy(carregando = true) }
val tarefas = repositorio.buscarTarefas() // suspend function
_uiState.update {
it.copy(tarefas = tarefas, carregando = false)
}
}
}
}
@Composable
fun TelaDeTarefas(viewModel: TarefasViewModel = viewModel()) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
if (uiState.carregando) {
CircularProgressIndicator()
} else {
LazyColumn {
items(uiState.tarefas) { tarefa ->
Text(text = tarefa, modifier = Modifier.padding(16.dp))
}
}
}
}
Navegação com Compose
A navegação entre telas em Compose ficou bem mais simples:
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable("home") {
TelaInicial(
onNavigateToDetalhes = { id ->
navController.navigate("detalhes/$id")
}
)
}
composable("detalhes/{id}") { backStackEntry ->
val id = backStackEntry.arguments?.getString("id")
TelaDetalhes(id = id)
}
}
}
Chamadas de rede com Coroutines
Aqui é onde Kotlin brilha no Android. Nada de callbacks ou AsyncTask:
class UsuarioRepository(private val api: ApiService) {
suspend fun buscarUsuarios(): Result<List<Usuario>> {
return try {
val response = api.getUsuarios()
Result.success(response)
} catch (e: Exception) {
Result.failure(e)
}
}
}
A palavra-chave suspend indica que essa função pode ser pausada sem bloquear a thread. Combinada com viewModelScope.launch, ela roda fora da main thread automaticamente.
Boas práticas para Android com Kotlin
- Use
StateFlowem vez deLiveDataem projetos novos — é mais idiomático em Kotlin e se integra melhor com coroutines - Prefira
valsobrevar— imutabilidade previne bugs e facilita o raciocínio sobre o código - Aplique a arquitetura recomendada: UI Layer > Domain Layer > Data Layer. Separar responsabilidades facilita a manutenção e os testes
- Escreva testes de Compose com
createComposeRule()— testes de UI garantem que mudanças não quebrem a experiência do usuário - Use Hilt ou Koin para injeção de dependências — evite instanciar dependências manualmente nos Composables e ViewModels
- Evite lógica de negócio em Composables — delegue pro ViewModel para manter as funções
@Composablefocadas apenas na renderização da UI - Modularize seu projeto — conforme o app cresce, separar features em módulos Gradle melhora o tempo de build e a organização do código
- Use
collectAsStateWithLifecycle()em vez decollectAsState()— ele respeita o ciclo de vida e para de coletar quando o app vai para background, economizando recursos
Testes de UI com Compose
Testar telas em Compose é simples e intuitivo. Usando createComposeRule(), você consegue verificar se os elementos estão visíveis e se as interações funcionam corretamente:
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun telaDeBoasVindas_exibeNomeDoUsuario() {
composeTestRule.setContent {
TelaDeBoasVindas(nome = "Karina")
}
composeTestRule
.onNodeWithText("Fala, Karina!")
.assertIsDisplayed()
composeTestRule
.onNodeWithText("Começar")
.assertIsDisplayed()
.performClick()
}
Você pode buscar elementos por texto, por testTag ou por semântica. O importante é cobrir os fluxos principais do app para garantir que regressões sejam detectadas rapidamente.
Conclusão
Kotlin e Android formam uma dupla imbatível em 2026. Com Jetpack Compose, coroutines e todo o ecossistema do Jetpack, desenvolver apps nunca foi tão produtivo e prazeroso. Para o backend do seu app, considere usar Kotlin com Spring Boot/Ktor, ou explore Go e Python como alternativas. Se você está entrando no mundo mobile, comece direto com Kotlin — não tem por que passar pelo Java primeiro.
No próximo post, vamos mergulhar nas coroutines e entender como funcionam por debaixo dos panos. Até lá!