alinaqi/android-kotlin

Desenvolvimento Android Kotlin com Coroutines, Jetpack Compose, Hilt e testes MockK

O que é android-kotlin?

Esta skill capacita agentes de IA (como Claude Code) a desenvolverem aplicações Android modernas utilizando Kotlin, com suporte nativo para Coroutines (programação assíncrona), Jetpack Compose (UI declarativa), Hilt (injeção de dependência baseada em Dagger) e MockK (testes unitários com mocks). O agente pode gerar código seguindo as melhores práticas do ecossistema Android, incluindo arquitetura MVVM, ViewModels, estados observáveis via StateFlow/Compose State, e repositórios com injeção de dependência. Também é útil para escrever testes unitários e de UI com MockK e Compose Test, além de realizar refatoração segura. A skill é projetada para funcionar com ferramentas que leem SKILL.md, como Claude Code, Cursor e Codex, fornecendo contexto detalhado para tarefas de desenvolvimento Android.

Funciona com~Claude Code~Codex CLI~Cursor
Part ofMobile
npx skills add https://github.com/alinaqi/claude-bootstrap/tree/main/skills/android-kotlin

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que android-kotlin faz?

Desenvolvimento Android Kotlin com Coroutines, Jetpack Compose, Hilt e testes MockK

Visão Geral

Esta skill fornece conhecimento especializado para desenvolvimento de aplicativos Android modernos usando Kotlin como linguagem principal, com foco em:

  • Coroutines para concorrência e tarefas assíncronas
  • Jetpack Compose para construção de interfaces de usuário declarativas
  • Hilt para injeção de dependência
  • MockK para testes unitários e de integração

Tecnologias Abordadas

Coroutines

  • Lançamento de corrotinas com viewModelScope, lifecycleScope e GlobalScope
  • Uso de async/await para execução paralela
  • Tratamento de exceções com try/catch e CoroutineExceptionHandler
  • Flow frio (flow, flowOf) e quente (SharedFlow, StateFlow)
  • Operadores como map, filter, catch, collect
  • Dispatchers (Dispatchers.IO, Dispatchers.Main, Dispatchers.Default)

Jetpack Compose

  • Funções @Composable e @Preview
  • Gerenciamento de estado com remember, mutableStateOf, StateFlow
  • Layouts: Column, Row, Box, LazyColumn, LazyRow
  • Componentes Material3: Button, TextField, Card, Scaffold, TopAppBar
  • Navegação com NavController e NavHost
  • Tema com MaterialTheme (cores, tipografia, formas)
  • Modificadores (Modifier.padding, Modifier.fillMaxWidth, Modifier.clickable)
  • Efeitos colaterais com LaunchedEffect, DisposableEffect, SideEffect

Hilt

  • @HiltAndroidApp para aplicação
  • @HiltViewModel para ViewModels injetáveis
  • @Inject para construtores e campos
  • Módulos com @Module e @InstallIn
  • Providers com @Provides e @Binds
  • Escopos: @Singleton, @ViewModelScoped, @ActivityScoped, @FragmentScoped
  • @EntryPoint para classes que não são suportadas por Hilt

MockK

  • Criação de mocks: mockk<>(), spyk<>()
  • Definição de comportamento: every { ... } returns ..., coEvery { ... }
  • Verificação de chamadas: verify { ... }, coVerify { ... }, verifySequence
  • Captura de argumentos: slot<>(), capture()
  • Relâmpago de regras: useRelaxed = true
  • Teste com ViewModel: runTest, TestCoroutineDispatcher
  • Uso com Compose: ComposeTestRule
  • Mocks parciais com spyk

Estrutura Recomendada de Projeto

app/
├── src/
│   ├── main/
│   │   ├── java/com/example/app/
│   │   │   ├── MainActivity.kt
│   │   │   ├── ui/
│   │   │   │   ├── screens/
│   │   │   │   ├── components/
│   │   │   │   └── theme/
│   │   │   ├── viewmodel/
│   │   │   ├── data/
│   │   │   │   ├── repository/
│   │   │   │   ├── local/
│   │   │   │   └── remote/
│   │   │   ├── di/
│   │   │   └── model/
│   │   └── res/
│   └── test/
│       └── java/com/example/app/
│           ├── viewmodel/
│           └── repository/
└── build.gradle.kts

Dependências comuns (build.gradle.kts)

dependencies {
    // Jetpack Compose
    implementation("androidx.compose.ui:ui:1.5.0")
    implementation("androidx.compose.material3:material3:1.1.0")
    implementation("androidx.compose.ui:ui-tooling-preview:1.5.0")
    implementation("androidx.activity:activity-compose:1.7.0")
    implementation("androidx.navigation:navigation-compose:2.7.0")

    // ViewModel
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.0")
    implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.0")

    // Coroutines
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.0")

    // Hilt
    implementation("com.google.dagger:hilt-android:2.47")
    kapt("com.google.dagger:hilt-compiler:2.47")
    implementation("androidx.hilt:hilt-navigation-compose:1.0.0")

    // Testes
    testImplementation("io.mockk:mockk:1.13.5")
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.0")
    testImplementation("androidx.arch.core:core-testing:2.2.0")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.5.0")
}

Exemplo de Uso

ViewModel com Hilt e Coroutines

@HiltViewModel
class MainViewModel @Inject constructor(
    private val repository: MyRepository
) : ViewModel() {

    private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()

    init {
        loadData()
    }

    fun loadData() {
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            try {
                val data = repository.fetchData()
                _uiState.value = UiState.Success(data)
            } catch (e: Exception) {
                _uiState.value = UiState.Error(e.message ?: "Erro desconhecido")
            }
        }
    }
}

Tela com Jetpack Compose

@Composable
fun MainScreen(viewModel: MainViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsState()

    when (val state = uiState) {
        is UiState.Loading -> CircularProgressIndicator()
        is UiState.Success -> ItemList(state.data)
        is UiState.Error -> Text("Erro: ${state.message}")
    }
}

Teste com MockK

class MainViewModelTest {
    private val repository: MyRepository = mockk()
    private lateinit var viewModel: MainViewModel

    @Before
    fun setup() {
        coEvery { repository.fetchData() } returns listOf()
        viewModel = MainViewModel(repository)
    }

    @Test
    fun `loadData deve retornar sucesso`() = runTest {
        val data = listOf(Item("Teste"))
        coEvery { repository.fetchData() } returns data

        viewModel.loadData()

        assertEquals(UiState.Success(data), viewModel.uiState.value)
    }
}

Boas Práticas

  • Utilize StateFlow no ViewModel e collectAsState() no Compose
  • Injete dependências via Hilt sempre que possível
  • Prefira viewModelScope para lançar corrotinas em ViewModels
  • Use coEvery e coVerify para funções suspend em MockK
  • Estruture a UI em componentes reutilizáveis
  • Use @Preview para visualizar componentes isoladamente
  • Mantenha o ViewModel livre de dependências do Android (exceto Application)
  • Teste ViewModels com runTest e TestCoroutineDispatcher

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Habilidades Relacionadas