Kotlin/JetpackComposeDevelopment Kotlin/JetpackComposeDevelopment

这项技能是为使用 Kotlin 和 Jetpack Compose 进行原生 Android 开发的专家提供的,包括 UI 组件生成、架构模式实现和 Gradle 构建操作。

移动开发 0 次安装 0 次浏览 更新于 2/25/2026

Kotlin/Jetpack Compose 开发技能

概览

这项技能提供了使用 Kotlin 和 Jetpack Compose 进行原生 Android 开发的专家能力。它能够生成 Compose UI 组件,实现现代 Android 架构模式,并全面操作 Gradle 构建。

允许使用的工具

  • bash - 执行 Gradle 命令,adb 和 Android SDK 工具
  • read - 分析 Kotlin 源文件和 Gradle 配置
  • write - 生成和修改 Kotlin 代码和 Compose composables
  • edit - 更新现有的 Kotlin 代码和配置
  • glob - 搜索 Kotlin 文件和 Android 资源
  • grep - 在 Android 代码库中搜索模式

能力

Jetpack Compose

  1. 可组合函数

    • 创建 Material Design 3 composables
    • 使用 Layout composable 实现自定义布局
    • 构建可重用的 UI 组件
    • 生成预览注释
    • 创建多预览配置
  2. 状态管理

    • 实现 remember 和 rememberSaveable
    • 使用状态提升模式
    • 配置 derivedStateOf 以计算状态
    • 实施 snapshotFlow 以进行副作用处理
    • 处理配置更改
  3. 导航

    • 使用 NavHost 配置 Compose 导航
    • 实现带参数的类型安全导航
    • 设置嵌套导航图
    • 使用 NavDeepLink 处理深度链接
    • 使用 BottomNavigation 实现底部导航

ViewModel 集成

  1. ViewModel 模式

    • 使用 Hilt 注入创建 ViewModel
    • 实施 StateFlow 和 SharedFlow
    • 配置 SavedStateHandle
    • 处理进程死亡恢复
    • 使用 viewModelScope 进行协程
  2. UI 状态管理

    • 设计密封类 UI 状态
    • 实施加载、错误和成功状态
    • 配置下拉刷新
    • 使用 Paging 3 处理分页
    • 实施搜索和防抖

Kotlin 协程

  1. 协程模式

    • 配置 CoroutineScope 和调度器
    • 实施结构化并发
    • 正确处理取消
    • 使用 SupervisorJob 进行错误隔离
    • 配置 ExceptionHandler
  2. Flow 模式

    • 创建冷和热 Flows
    • 实施 StateFlow 和 SharedFlow
    • 配置 Flow 操作符
    • 使用 buffer 处理背压
    • 使用 map、filter、combine 转换 Flows

依赖注入

  1. Hilt 集成
    • 配置 Hilt 模块
    • 实施 @Inject 注解
    • 设置 ViewModelComponent
    • 配置 Singleton 和 Scoped 绑定
    • 使用 @EntryPoint 为框架类

Gradle 构建系统

  1. 构建配置

    • 使用 Kotlin DSL 配置 build.gradle.kts
    • 设置构建变体和风味
    • 配置 ProGuard/R8 规则
    • 实施版本目录
    • 设置复合构建
  2. KSP/KAPT

    • 配置 Kotlin 符号处理
    • 使用 KSP 设置 Room
    • 使用 KAPT 配置 Hilt
    • 使用自定义处理器生成代码

测试

  1. 测试框架
    • 编写 JUnit 5 单元测试
    • 实施 Compose UI 测试
    • 配置测试规则和固定装置
    • 使用 MockK 模拟依赖项
    • 设置 Robolectric 进行 JVM 测试

目标流程

这项技能与以下流程集成:

  • jetpack-compose-ui.js - Compose UI 开发
  • android-room-database.js - Room 持久性
  • firebase-cloud-messaging.js - FCM 集成
  • android-playstore-publishing.js - Play Store 提交

依赖项

必需

  • Android Studio Hedgehog 或更高版本
  • Android SDK 34+
  • Kotlin 1.9+
  • Gradle 8.2+

可选

  • Android 模拟器
  • Firebase 工具
  • adb (Android Debug Bridge)
  • Layout Inspector

配置

项目结构

app/
├── src/
│   ├── main/
│   │   ├── kotlin/com/example/myapp/
│   │   │   ├── MyApplication.kt
│   │   │   ├── MainActivity.kt
│   │   │   ├── di/
│   │   │   │   └── AppModule.kt
│   │   │   ├── data/
│   │   │   │   ├── repository/
│   │   │   │   ├── local/
│   │   │   │   └── remote/
│   │   │   ├── domain/
│   │   │   │   ├── model/
│   │   │   │   ├── repository/
│   │   │   │   └── usecase/
│   │   │   └── ui/
│   │   │       ├── theme/
│   │   │       ├── navigation/
│   │   │       └── feature/
│   │   ├── res/
│   │   └── AndroidManifest.xml
│   ├── test/
│   └── androidTest/
├── build.gradle.kts
└── proguard-rules.pro

版本目录

# gradle/libs.versions.toml
[versions]
kotlin = "1.9.21"
compose-bom = "2024.01.00"
hilt = "2.50"
room = "2.6.1"
lifecycle = "2.7.0"

[libraries]
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
compose-ui = { group = "androidx.compose.ui", name = "ui" }
compose-material3 = { group = "androidx.compose.material3", name = "material3" }
compose-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }

[plugins]
android-application = { id = "com.android.application", version = "8.2.0" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
ksp = { id = "com.google.devtools.ksp", version = "1.9.21-1.0.16" }

使用示例

创建可组合屏幕

// ui/feature/home/HomeScreen.kt
package com.example.myapp.ui.feature.home

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen(
    viewModel: HomeViewModel = hiltViewModel(),
    onItemClick: (String) -> Unit
) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("Home") }
            )
        }
    ) { paddingValues ->
        when (val state = uiState) {
            is HomeUiState.Loading -> {
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(paddingValues),
                    contentAlignment = Alignment.Center
                ) {
                    CircularProgressIndicator()
                }
            }
            is HomeUiState.Success -> {
                LazyColumn(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(paddingValues),
                    contentPadding = PaddingValues(16.dp),
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    items(state.items, key = { it.id }) { item ->
                        ItemCard(
                            item = item,
                            onClick = { onItemClick(item.id) }
                        )
                    }
                }
            }
            is HomeUiState.Error -> {
                ErrorContent(
                    message = state.message,
                    onRetry = viewModel::retry,
                    modifier = Modifier.padding(paddingValues)
                )
            }
        }
    }
}

@Composable
private fun ItemCard(
    item: Item,
    onClick: () -> Unit,
    modifier: Modifier = Modifier
) {
    Card(
        onClick = onClick,
        modifier = modifier.fillMaxWidth()
    ) {
        Column(
            modifier = Modifier.padding(16.dp)
        ) {
            Text(
                text = item.title,
                style = MaterialTheme.typography.titleMedium
            )
            Spacer(modifier = Modifier.height(4.dp))
            Text(
                text = item.description,
                style = MaterialTheme.typography.bodyMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
        }
    }
}

实施 ViewModel

// ui/feature/home/HomeViewModel.kt
package com.example.myapp.ui.feature.home

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class HomeViewModel @Inject constructor(
    private val getItemsUseCase: GetItemsUseCase
) : ViewModel() {

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

    init {
        loadItems()
    }

    private fun loadItems() {
        viewModelScope.launch {
            _uiState.value = HomeUiState.Loading

            getItemsUseCase()
                .catch { e ->
                    _uiState.value = HomeUiState.Error(e.message ?: "Unknown error")
                }
                .collect { items ->
                    _uiState.value = HomeUiState.Success(items)
                }
        }
    }

    fun retry() {
        loadItems()
    }
}

sealed interface HomeUiState {
    data object Loading : HomeUiState
    data class Success(val items: List<Item>) : HomeUiState
    data class Error(val message: String) : HomeUiState
}

配置导航

// ui/navigation/NavGraph.kt
package com.example.myapp.ui.navigation

import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.example.myapp.ui.feature.home.HomeScreen
import com.example.myapp.ui.feature.detail.DetailScreen

sealed class Screen(val route: String) {
    data object Home : Screen("home")
    data object Detail : Screen("detail/{itemId}") {
        fun createRoute(itemId: String) = "detail/$itemId"
    }
}

@Composable
fun NavGraph(
    navController: NavHostController,
    startDestination: String = Screen.Home.route
) {
    NavHost(
        navController = navController,
        startDestination = startDestination
    ) {
        composable(Screen.Home.route) {
            HomeScreen(
                onItemClick = { itemId ->
                    navController.navigate(Screen.Detail.createRoute(itemId))
                }
            )
        }

        composable(
            route = Screen.Detail.route,
            arguments = listOf(
                navArgument("itemId") { type = NavType.StringType }
            )
        ) { backStackEntry ->
            val itemId = backStackEntry.arguments?.getString("itemId") ?: return@composable
            DetailScreen(
                itemId = itemId,
                onBackClick = { navController.popBackStack() }
            )
        }
    }
}

配置 Hilt 模块

// di/AppModule.kt
package com.example.myapp.di

import android.content.Context
import androidx.room.Room
import com.example.myapp.data.local.AppDatabase
import com.example.myapp.data.remote.ApiService
import com.example.myapp.data.repository.ItemRepositoryImpl
import com.example.myapp.domain.repository.ItemRepository
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
    @Binds
    @Singleton
    abstract fun bindItemRepository(impl: ItemRepositoryImpl): ItemRepository
}

@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext context: Context): AppDatabase {
        return Room.databaseBuilder(
            context,
            AppDatabase::class.java,
            "app_database"
        ).build()
    }

    @Provides
    fun provideItemDao(database: AppDatabase) = database.itemDao()
}

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
    @Provides
    @Singleton
    fun provideRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
    }

    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }
}

构建命令

# 清理构建
./gradlew clean

# 构建 debug APK
./gradlew assembleDebug

# 构建 release AAB
./gradlew bundleRelease

# 运行单元测试
./gradlew testDebugUnitTest

# 运行仪器测试
./gradlew connectedDebugAndroidTest

# 运行 lint
./gradlew lintDebug

# 安装在设备上
./gradlew installDebug

质量门

代码质量

  • Kotlin 编译器警告视为错误
  • Detekt/ktlint 合规性
  • 无弃用 API 使用
  • 适当的协程作用域管理

性能基准测试

  • 应用启动 < 500ms(冷启动)
  • 滚动和动画期间 60fps
  • 无内存泄漏(LeakCanary 验证)
  • 最小化重组

测试覆盖率

  • 单元测试覆盖率 > 80%
  • 关键流程的 UI 测试覆盖率
  • UI 组件的截图测试

错误处理

常见问题

  1. Gradle 同步失败

    ./gradlew --refresh-dependencies
    
  2. KSP/KAPT 问题

    ./gradlew clean && ./gradlew kspDebugKotlin
    
  3. 模拟器问题

    adb kill-server && adb start-server
    
  4. Compose 预览问题

    # 使缓存无效:文件 > 使缓存无效 / 重启
    

相关技能

  • android-room - Room 数据库集成
  • firebase-mobile - Firebase 服务
  • mobile-testing - 全面测试
  • google-play-console - Play Store 发布

版本历史

  • 1.0.0 - 初始发布,具有核心 Kotlin/Compose 功能