🤖 Android jetpack compose用法总结

Android Jetpack Compose 是 Google 推出的用于构建原生 Android UI 的现代工具包。它使用更少的代码、强大的工具和直观的 Kotlin API,简化并加速了 Android 上的 UI 开发。
1. 核心概念
声明式 UI
Compose 使用声明式 API,这意味着你只需要描述 UI 应该是什么样子,Compose 会负责处理渲染和更新。
@Composable 注解
所有 Compose UI 函数都必须带有 @Composable 注解。
1 |
|
2. 基础组件
Compose 提供了一系列开箱即用的 Material Design 组件。
- Text: 显示文本。
- Button: 按钮交互。
- Image: 显示图片。
- TextField: 文本输入框。
- Icon: 显示图标。
1 |
|
3. 布局 (Layouts)
标准布局
- Column: 垂直排列子元素 (类似 LinearLayout vertical)。
- Row: 水平排列子元素 (类似 LinearLayout horizontal)。
- Box: 堆叠子元素 (类似 FrameLayout)。
1 |
|
列表 (Lists)
使用 LazyColumn 和 LazyRow 来处理大量数据,相当于 RecyclerView。
1 |
|
Scaffold
Scaffold 实现了基本的 Material Design 布局结构,如 TopBar, BottomBar, FloatingActionButton, Drawer 等。
1 |
|
4. 修饰符 (Modifiers)
Modifier 是 Compose 的核心,用于修饰 Composable 的大小、布局、行为和外观。
- 布局:
fillMaxSize(),width(),height(),padding(). - 行为:
clickable(),scrollable(). - 外观:
background(),border(),clip().
注意: Modifier 的顺序很重要。
1 | Text( |
5. 状态管理 (State Management)
remember & mutableStateOf
mutableStateOf: 创建一个可观察的状态。remember: 在重组 (Recomposition) 期间保存状态。
1 |
|
状态提升 (State Hoisting)
将状态移动到调用者,使组件变为无状态 (Stateless),便于复用和测试。
1 |
|
ViewModel 集成
通常使用 ViewModel 来管理屏幕级别的状态。
1 | class MyViewModel : ViewModel() { |
6. 副作用 (Side Effects)
在 Composable 中处理非 UI 逻辑(如网络请求、定时器)。
- LaunchedEffect: 在协程作用域中运行挂起函数。
- DisposableEffect: 需要清理的副作用(如注册/注销监听器)。
- SideEffect: 将 Compose 状态发布到非 Compose 代码。
1 |
|
7. 互操作性 (Interoperability)
Compose in View (在 XML 中使用 Compose)
使用 ComposeView。
1 | <androidx.compose.ui.platform.ComposeView |
1 | composeView.setContent { |
View in Compose (在 Compose 中使用 View)
使用 AndroidView。
1 |
|
8. 进阶用法 (Advanced Usage)
动画 (Animation)
Compose 提供了强大的动画 API。
- 简单值动画:
animateFloatAsState,animateColorAsState。 - 可见性动画:
AnimatedVisibility。 - 内容切换:
AnimatedContent。
1 | var visible by remember { mutableStateOf(true) } |
导航 (Navigation)
使用 Navigation Compose 库管理页面跳转。
1 | val navController = rememberNavController() |
CompositionLocal
用于在组件树中隐式传递数据(如主题、Context),避免层层传递参数。
1 | val LocalUser = compositionLocalOf { User("Unknown") } |
9. 常见误区 (Common Pitfalls)
1. Padding 到底是内边距还是外边距?(Modifier 顺序)
这是初学者最容易困惑的地方。Compose 中没有专门的 margin 修饰符,只有 padding。
padding 的作用取决于它在 Modifier 链中的位置。Modifier 是从左到右(或从外到内)顺序应用的,每一个 Modifier 都会包装(Wrap)前一个结果。
- 作为外边距 (Margin): 如果
padding在background或border之前应用,它表现得像外边距(因为背景色是在 padding 之后才绘制的,所以 padding 区域没有背景)。 - 作为内边距 (Padding): 如果
padding在background或border之后应用,它表现得像内边距(因为背景色已经绘制了,padding 只是在背景内部挤压内容)。
为什么这么设计?
这种设计基于单一职责原则和链式调用。传统的 View 系统区分 margin 和 padding 是因为 View 是一个单一的对象,属性是固定的。而 Compose 的 Modifier 是一个有序的修饰链,通过组合简单的原子操作(padding, background)来构建复杂的 UI 效果。这消除了 “margin collapsing”(外边距折叠)等复杂性,也使得创建多层边框或复杂的间隔变得非常直观。
1 | // 示例:同时实现外边距和内边距 |
2. 在 Composable 中直接执行副作用
不要在 Composable 函数体中直接进行网络请求或数据库操作,这会导致每次重组都重复执行。
- 正确做法: 使用
LaunchedEffect或DisposableEffect。
3. 重组循环 (Recomposition Loop)
在 Composable 中更新状态,而该状态的读取又触发了同一个 Composable 的重组。
1 | // 错误示例 |
4. 列表缺少 Key
在 LazyColumn 中,如果不指定 key,当列表项发生变化(如插入、删除)时,Compose 可能无法正确复用状态,导致性能下降或状态丢失。
1 | items(items, key = { it.id }) { item -> ... } |
10. 面试常见问题 (Interview Q&A)
Q1: 什么是重组 (Recomposition)?它是如何工作的?
A: 重组是 Compose 更新 UI 的机制。当 Composable 函数依赖的状态发生变化时,Compose 会重新执行该函数(及其子函数)以生成新的 UI 树。Compose 具有智能跳过机制(Smart Recomposition),只会重组受影响的部分,跳过参数未变化的组件。
Q2: remember 和 rememberSaveable 有什么区别?
A:
remember: 将对象保存在内存中。当 Composable 销毁(从组合中移除)时,状态丢失。配置更改(如旋转屏幕)时状态也会丢失。rememberSaveable: 除了具备remember的功能外,还能在配置更改(Configuration Change)和进程重建后恢复状态(通过 Bundle 保存)。
Q3: LaunchedEffect 和 DisposableEffect 的区别?
A:
LaunchedEffect: 用于启动协程。当进入组合时启动,离开组合时取消。适合一次性操作或挂起函数。DisposableEffect: 用于需要清理的副作用(非协程)。当进入组合时执行onActive,离开组合时执行onDispose。适合注册/注销回调、监听器。
Q4: 为什么 Compose 性能比 View 高(或相当)?
A:
- 扁平化布局: Compose 布局嵌套不会像 View 那样导致指数级的测量成本(Compose 规定布局只能测量子元素一次)。
- 更少的代码: 减少了 XML 解析和 findViewById 的开销。
- 智能重组: 只更新变化的部分。
Q5: 什么是 SideEffect?
A: SideEffect 是一个 Compose 副作用 API,用于在每次重组成功完成后执行代码。通常用于将 Compose 的状态同步给非 Compose 的系统(如更新系统状态栏颜色)。
11. 常用资源
- 官方文档: developer.android.com/jetpack/compose
- Accompanist: 一组常用的 Compose 扩展库 (如 Pager, Permissions, System UI Controller)。
- 本文链接: https://blog.saltpi.cn/article/android-jetpack-compose/
- 版权声明: 本博客所有文章除特别声明外,均采用 ©BY-NC-SA 许可协议。转载请注明出处!