Kotlin é a linguagem oficial de desenvolvimento do Android e, em 2026, o Jetpack Compose substituiu os layouts XML como estrutura de IU principal. Com corrotinas para assíncrono, Flow para fluxos reativos e Hilt para injeção de dependência, o desenvolvimento moderno do Android está mais produtivo do que nunca. Este guia cobre tudo, desde a configuração do projeto até os padrões de produção.
📋 Table of Contents
Configuração do projeto
Android Studio Hedgehog (or newer) — recommended IDE
New project:
Template: Empty Activity (Compose)
Language: Kotlin
Min SDK: 24 (Android 7.0, 96% coverage)
Build System: Gradle with Kotlin DSL (build.gradle.kts)
Noções básicas do Jetpack Compose
// MainActivity.kt
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
// Content here
UserListScreen()
}
}
}
}
// Composable functions = UI components
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
.clickable { onClick() },
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Row(
modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
AsyncImage( // Coil library
model = user.avatarUrl,
contentDescription = "Avatar",
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
)
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(text = user.name, style = MaterialTheme.typography.titleMedium)
Text(
text = user.email,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.outline
)
}
}
}
}
// State management
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "Count: $count", style = MaterialTheme.typography.headlineMedium)
Button(onClick = { count++ }) {
Text("Increment")
}
}
}
ViewModel com StateFlow
// UserViewModel.kt
@HiltViewModel
class UserViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() {
// UI state
sealed class UiState {
object Loading : UiState()
data class Success(val users: List<User>) : UiState()
data class Error(val message: String) : UiState()
}
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
init {
loadUsers()
}
private fun loadUsers() {
viewModelScope.launch {
_uiState.value = UiState.Loading
userRepository.getUsers()
.catch { e -> _uiState.value = UiState.Error(e.message ?: "Unknown error") }
.collect { users -> _uiState.value = UiState.Success(users) }
}
}
fun createUser(name: String, email: String) {
viewModelScope.launch {
try {
userRepository.createUser(User(name = name, email = email))
loadUsers() // refresh
} catch (e: Exception) {
_uiState.value = UiState.Error("Failed to create user: ${e.message}")
}
}
}
}
// UserListScreen.kt
@Composable
fun UserListScreen(viewModel: UserViewModel = hiltViewModel()) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
when (val state = uiState) {
is UserViewModel.UiState.Loading -> CircularProgressIndicator()
is UserViewModel.UiState.Error -> ErrorMessage(state.message)
is UserViewModel.UiState.Success -> UserList(
users = state.users,
onUserClick = { /* navigate */ }
)
}
}
Retrofit + Corrotinas
// ApiService.kt
interface ApiService {
@GET("users")
suspend fun getUsers(): List<UserResponse>
@GET("users/{id}")
suspend fun getUser(@Path("id") id: Int): UserResponse
@POST("users")
suspend fun createUser(@Body request: CreateUserRequest): UserResponse
}
// NetworkModule.kt (Hilt)
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor { chain ->
val request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer ${BuildConfig.API_TOKEN}")
.build()
chain.proceed(request)
}
.build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideApiService(retrofit: Retrofit): ApiService =
retrofit.create(ApiService::class.java)
}
// UserRepository.kt
class UserRepositoryImpl @Inject constructor(
private val apiService: ApiService,
private val userDao: UserDao // Room local cache
) : UserRepository {
override fun getUsers(): Flow<List<User>> = flow {
// Emit cached data first
userDao.getAllUsers().collect { emit(it.map(UserEntity::toDomain)) }
// Fetch fresh data
val freshUsers = apiService.getUsers()
userDao.insertUsers(freshUsers.map(UserResponse::toEntity))
}
}
Banco de dados de salas
// User entity
@Entity(tableName = "users")
data class UserEntity(
@PrimaryKey val id: Int,
val name: String,
val email: String,
val createdAt: Long = System.currentTimeMillis()
)
// DAO
@Dao
interface UserDao {
@Query("SELECT * FROM users ORDER BY createdAt DESC")
fun getAllUsers(): Flow<List<UserEntity>>
@Query("SELECT * FROM users WHERE id = :id")
suspend fun getUserById(id: Int): UserEntity?
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUsers(users: List<UserEntity>)
@Delete
suspend fun deleteUser(user: UserEntity)
}
// Database
@Database(entities = [UserEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
// Hilt module
@Provides
@Singleton
fun provideDatabase(@ApplicationContext ctx: Context): AppDatabase {
return Room.databaseBuilder(ctx, AppDatabase::class.java, "app_db").build()
}
Navegação com Compose
// Navigation
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "users") {
composable("users") {
UserListScreen(
onUserClick = { userId -> navController.navigate("user/$userId") }
)
}
composable("user/{userId}") { backStackEntry ->
val userId = backStackEntry.arguments?.getString("userId")?.toIntOrNull()
UserDetailScreen(userId = userId)
}
composable("create-user") {
CreateUserScreen(onCreated = { navController.popBackStack() })
}
}
}
O desenvolvimento Kotlin Android em 2026 com Jetpack Compose, ViewModel + StateFlow, Hilt para DI, Room para armazenamento local e Retrofit para rede é uma pilha madura e produtiva. A arquitetura é limpa e testável – cada camada pode ser testada de forma independente com utilitários de teste que reconhecem corrotinas.
🔗 Share this article
✍️ Leave a Comment