移动开发··3 分钟

Jetpack Compose 现代 Android 开发实践

分享使用 Jetpack Compose 构建 Android 应用的经验,包括架构设计、状态管理与性能优化

#Android#Kotlin#Compose#MVVM

Compose 改变了什么

Jetpack Compose 不仅仅是 Android 的新 UI 框架,它从根本上改变了我们思考 UI 的方式。从命令式的 View 操作转向声明式的函数描述,这种范式转换带来的好处远超表面的代码简化。

架构选择

在 Compose 时代,推荐的架构是:

UI (Compose) → ViewModel → Repository → Data Source

关键原则:

  • 单向数据流 — State 向下,Event 向上
  • 状态提升 — 将状态提升到合适的层级
  • 副作用管理 — 使用 LaunchedEffectrememberCoroutineScope

状态管理

Compose 的状态管理是核心也是最容易出问题的地方:

@Composable
fun UserScreen(viewModel: UserViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
    
    UserContent(
        state = uiState,
        onAction = viewModel::handleAction,
    )
}

几个实践建议:

  1. 使用 StateFlow 而非 LiveData
  2. UI State 用密封类(sealed class)表示
  3. 将业务逻辑放在 ViewModel 中,Compose 函数只负责渲染

性能优化

重组(Recomposition)

理解重组是 Compose 性能优化的基础。当 State 变化时,Compose 会重新调用读取了该 State 的 composable 函数。关键是如何减少不必要的重组:

  • 使用 derivedStateOf 派生状态
  • 使用 remember 缓存计算结果
  • 使用 key 帮助 Compose 识别列表项

列表性能

LazyColumn 的性能关键在于 key 的正确使用:

LazyColumn {
    items(
        items = users,
        key = { it.id }  // 稳定的 key 很重要
    ) { user ->
        UserItem(user = user)
    }
}

实际踩坑

导航与状态恢复

Navigation Compose 的状态恢复在复杂场景下会出现问题,特别是涉及底部导航栏 + 嵌套导航时。解决方案是将每个 tab 的状态独立管理。

点击涟漪与手势冲突

自定义组件中的手势处理经常与系统的点击涟漪效果冲突,需要理解 Modifier 的顺序和 pointerInput 的工作原理。

总结

Compose 代表了 Android UI 开发的未来。虽然学习曲线存在,但一旦掌握声明式思维,开发效率和代码质量都会有显著提升。