Skip to content

使用 Jetpack Compose 构建现代化 Android UI 的专家级指南

通过引入标准的 MVI/MVVM 架构模式、类型安全导航和性能调优技巧,帮助开发者将 Android 界面从传统的 XML 布局迁移到声明式的 Jetpack Compose,并构建生产级别的 UI 体系。

为什么需要这个技能

传统的 Android XML 布局模式在处理复杂 UI 状态时极其繁琐,且容易导致状态不一致。Jetpack Compose 引入了声明式 UI 范式,但如果缺乏系统的方法论,开发者容易在状态管理(State Management)和重组(Recomposition)性能上踩坑。

掌握本技能可以确保你不仅能写出运行正常的 Compose 代码,还能通过 @StablederivedStateOf 等高级特性优化性能,并利用最新的类型安全导航方案替代易出错的字符串路由。

适用场景

  • 从零开始构建一个基于 Jetpack Compose 的现代化 Android 项目。
  • 将旧有的 XML 布局逐步迁移至 Compose。
  • 实现复杂的状态驱动界面,如需要频繁更新的实时数据面板。
  • 优化应用性能,解决 Compose 界面卡顿或不必要的重组问题。
  • 实现一个类型安全的页面跳转导航体系。

核心工作流

1. 依赖与环境配置

libs.versions.toml 中管理 Compose BOM(物料清单),确保所有 Compose 库版本兼容,避免因版本冲突导致编译失败。

2. 状态管理架构 (MVI/MVVM)

采用 ViewModel 结合 StateFlow 暴露 UI 状态。核心原则是:单一数据源,单向数据流

  • 使用 MutableStateFlow 在内部更新状态。
  • 对外暴露不可变的 StateFlow,防止视图层直接修改状态。
kotlin
// UI 状态定义
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) }
            try {
                val user = userRepository.getUser()
                _uiState.update { it.copy(user = user, isLoading = false) }
            } catch (e: Exception) {
                _uiState.update { it.copy(error = e.message, isLoading = false) }
            }
        }
    }
}

3. 构建状态无关的 Composable

将 Screen 级组件(依赖 ViewModel)与 Content 级组件(仅依赖数据和回调)分离,提高组件的可测试性和可复用性。

kotlin
@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)
            }
        }
    }
}

4. 实现类型安全导航

利用最新版本的 Navigation Compose,通过 @Serializable 对象替代字符串路径。

kotlin
@Serializable
object Home

@Serializable
data class Profile(val userId: String)

@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)
        }
    }
}

性能最佳实践

  • 减少重组:使用 rememberderivedStateOf 避免在重组期间进行重复的昂贵计算。
  • 稳定性标注:对于包含 List 等不稳定类型的数据类,使用 @Immutable@Stable 标注,以启用智能重组跳过。
  • 副作用处理:仅在 LaunchedEffect 中处理一次性副作用(如显示 Snackbar)。
  • 禁止在 Composable 中直接计算:不要在函数体中直接进行排序或过滤操作,必须将其包裹在 remember 中。

下载和安装

下载 android-jetpack-compose-expert 中文版 Skill ZIP

解压后将目录放入你的 AI 工具 skills 文件夹,重启工具后即可使用。具体路径参考内附的 USAGE.zh.md

你可能还需要

暂无推荐