关于 android-jetpack-compose-expert
面向 Android 开发者的 Jetpack Compose 开发指导技能,涵盖架构、状态管理、导航和性能优化,适用于新建项目及 XML 布局迁移。
主要功能
- 01使用 ViewModel 与 StateFlow 管理状态
- 02MVI 和 MVVM 模式指导
- 03类型安全的 Navigation Compose
- 04重组性能优化建议
- 05副作用处理实践
适用场景
- 01启动 Jetpack Compose 应用
- 02将 XML 布局迁移到 Compose
- 03管理 UI 状态与副作用
- 04排查重组性能问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill android-jetpack-compose-expert安装后在 Claude Code 中输入/android-jetpack-compose-expert确认已加载。
详细介绍
Android Jetpack Compose 专家
概述
这是一份全面指南,介绍如何使用 Jetpack Compose 构建可用于生产环境的 Android 应用。本技能涵盖架构模式、使用 ViewModel 管理状态、类型安全的导航以及性能优化技巧。
适用场景
- 使用 Jetpack Compose 启动新的 Android 项目时。
- 将旧版 XML 布局迁移到 Compose 时。
- 实现复杂的 UI 状态管理和副作用时。
- 优化 Compose 性能(重组次数、稳定性)时。
- 设置类型安全的 Navigation 时。
分步指南
1. 项目设置与依赖项
确保 libs.versions.toml 包含必需的 Compose BOM 和库。
[versions]
composeBom = "2024.02.01"
activityCompose = "1.8.2"
[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
2. 状态管理模式(MVI/MVVM)
使用 ViewModel 和 StateFlow 暴露 UI 状态。避免暴露 MutableStateFlow。
// UI State Definition
data class UserUiState(
val isLoading: Boolean = false,
val user: User? = null,
val error: String? = null
)
// ViewModel
class UserViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() {
private val _uiState = MutableStateFlow(UserUiState())
val uiState: StateFlow<UserUiState> = _uiState.asStateFlow()
fun loadUser() {
viewModelScope.launch {
_uiState.update { it.copy(isLoading = true, error = null) }
try {
val user = userRepository.getUser()
_uiState.update { it.copy(user = user, isLoading = false) }
} catch (e: kotlinx.coroutines.CancellationException) {
throw e
} catch (e: Exception) {
_uiState.update { it.copy(error = e.message, isLoading = false) }
}
}
}
}
3. 创建 Screen Composable
在 “Screen” Composable 中使用状态,并将数据传递给无状态组件。
@Composable
fun UserScreen(
viewModel: UserViewModel = hiltViewModel()
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
UserContent(
uiState = uiState,
onRetry = viewModel::loadUser
)
}
@Composable
fun UserContent(
uiState: UserUiState,
onRetry: () -> Unit
) {
Scaffold { padding ->
Box(modifier = Modifier.padding(padding)) {
when {
uiState.isLoading -> CircularProgressIndicator()
uiState.error != null -> ErrorView(uiState.error, onRetry)
uiState.user != null -> UserProfile(uiState.user)
}
}
}
}
上面的依赖项版本是历史示例,并非当前推荐的技术栈。类型安全导航还需要兼容的 Navigation Compose、Kotlin 序列化插件和依赖项;生命周期状态收集和 Hilt 需要各自的依赖项、导入和设置。Fragment 需要项目中的 User/Repository/View 组件。请有意触发初始加载(例如在 ViewModel init 中或通过带键的 effect);仅调用 onRetry 不会加载第一个 user。避免加载任务重叠,也不要在 UI 中暴露原始服务器异常消息。
示例
示例 1:类型安全导航
使用新版 Navigation Compose 类型安全功能(近期版本提供)。
// Define Destinations
@Serializable
object Home
@Serializable
data class Profile(val userId: String)
// Setup NavHost
@Composable
fun AppNavHost(navController: NavHostController) {
NavHost(navController, startDestination = Home) {
composable<Home> {
HomeScreen(onNavigateToProfile = { id ->
navController.navigate(Profile(userId = id))
})
}
composable<Profile> { backStackEntry ->
val profile: Profile = backStackEntry.toRoute()
ProfileScreen(userId = profile.userId)
}
}
}
最佳实践
- ✅ 应该: 使用
remember和derivedStateOf,尽量减少重组期间不必要的计算。 - ✅ 应该: 仅在类型确实遵守相应约定时才使用
@Immutable/@Stable;不要通过给可变集合添加注解来掩盖不稳定性。优先使用不可变数据,并检查编译器报告(Android 指南)。 - ✅ 应该: 使用
LaunchedEffect处理由状态变化触发的一次性副作用(例如显示 Snackbar)。 - ❌ 不要: 不使用
remember就直接在 Composable 函数体内执行耗时操作(例如排序列表)。 - ❌ 不要: 将
ViewModel实例传递给子组件。只传递数据(状态)和 lambda 回调(事件)。
故障排除
问题: 无限重组循环。 解决方案: 仅创建新对象并不会导致无限循环。检查是否在组合阶段更新了被观察的状态,从而形成反馈循环;这类更新应放在副作用或回调中。使用 Layout Inspector 调试重组次数。
限制
- 仅当任务明确符合上述范围时才使用此技能。
- 不要将输出视为替代环境特定验证、测试或专家审查的方案。
- 如果缺少必要的输入、权限、安全边界或成功标准,请暂停并请求澄清。