【Jetpack Compose进阶学与练】第14课:系列收尾复习总结;Compose项目常见坑点汇总;学习路线与后续学习方向
前言
本套教程从第1课从零搭建Compose开始,依次学习基础布局、Modifier修饰器、状态与交互、 remember ‑ rememberSaveable 、副作用Effect、下拉弹窗、MVI架构、性能优化、Navigation导航、SavedStateHandle、项目分包模块化,最后第13课完成简易笔记App实战。
本节课整体复盘整套知识点;梳理高频踩坑清单;给出后续学习路线。
知识点清单
- 整套课程核心知识点复盘梳理
- Compose开发高频坑点汇总(状态、重组、导航、生命周期、内存泄漏)
- MVI架构开发的标准开发流程
- 项目选型思考:单Activity架构适用边界
- 后续进阶学习路线(动画、自定义Layout、图形绘制、跨端KMP)
整套课程知识复盘
- 基础UI层(第1‑4课)
Column、Row、Box三大基础布局;Modifier修饰器控制尺寸、边距、背景;Modifier执行顺序非常关键;Modifier链式顺序会影响最终渲染效果。 - 状态与交互(第5‑8课)
状态提升原则;TextField文本输入; remember 页面重组时保留状态; rememberSaveable 屏幕旋转重建保存简单状态;
副作用体系: LaunchedEffect ;理解重组生命周期;不要直接在Composable顶层写网络请求;网络请求放到ViewModel。 - 性能专题(第9课)
重组Recomposition; remember 缓存计算; derivedStateOf 派生状态过滤无效状态变更;
LazyColumn列表务必使用业务唯一id作为item的key,禁止使用数组下标index;优先使用不可变val数据类,减少意外无效重组。 - 导航与状态保存(第10‑11课)
Navigation‑Compose;NavHost、NavController;页面路径参数与查询参数;popUpTo清理回退栈;
⚠️ NavController禁止保存进ViewModel,会内存泄漏;
SavedStateHandle基于Bundle,适合少量简单数据抗进程重启;大数据业务持久化优先Room。 - 工程架构(第12‑13课)
单Activity架构;分包 vs 模块化;单向依赖原则;
MVI三要素:Intent(用户意图)‑UiState(常驻页面状态)‑Effect(一次性事件Toast、导航);
分层:UI‑ViewModel‑Repository‑Data(Room/Retrofit);Room配合Flow实现响应式数据,数据变更自动刷新UI;
实战简易笔记App完整跑通整套数据流。
Compose高频坑点汇总
- 状态相关坑
- 使用普通 remember ,屏幕旋转之后状态直接丢失;少量状态改用 rememberSaveable ;大量业务数据走Room。
- Effect一次性事件误用 StateFlow ;页面重回之后重复消费旧事件;一次性事件优先 SharedFlow 。
- 重组性能坑
- LazyColumn不设置key,增删列表数据之后出现item闪烁错乱。
- 传入Composable可变集合(MutableList);修改集合内部元素Compose无法感知变更,界面不会刷新;必须使用不可变List配合State。
- 高频变化原始状态直接驱动UI,没有 derivedStateOf 过滤,疯狂无效重组造成卡顿。
- 导航与内存泄漏坑
- 将 NavController 保存到ViewModel;ViewModel生命周期更长引发内存泄漏;导航回调应该由UI层执行。
- popUpTo的 inclusive 取值错误;登录跳转首页之后按返回键依然回到登录页面。
- 架构分层坑
- 在Compose页面直接发起网络请求、直接调用Dao数据库;跳过ViewModel与Repository;业务散落在UI组件;后期维护困难。
- 模块化的时候出现循环依赖;common基础模块反向依赖上层业务模块。
- SavedStateHandle误区
误以为SavedStateHandle可以存列表、Bitmap图片;Bundle有容量上限;只适合少量简单键‑值。
MVI标准开发流程(开发的时候可以照着这个流程写页面)
- 定义密封类 Intent:列举本页面所有用户交互动作(点击、下拉刷新、新增、删除)
- 定义密封类 UiState:页面加载中 /成功(携带数据) /错误;常驻渲染状态
- 定义密封类 Effect:一次性事件,Toast、弹窗、页面跳转
- ViewModel接收Intent;调用Repository;访问数据源;更新UiState;发送Effect
- UI层:collectAsStateWithLifecycle收集UiState渲染界面;收集Effect处理一次性事件;响应用户交互,调用sendIntent发送意图。
单Activity架构适用边界
✅适合:绝大多数业务App;Compose原生开发;依靠Navigation‑Compose管理回退栈;页面切换开销小;统一页面转场动画。
⚠️局限:没有独立Activity销毁回收;需要自己留意页面退出之后协程的取消;
部分特殊场景仍然保留多Activity:第三方SDK登录页面、相机页面;支付SDK页面。不必强行全部单Activity。
后续进阶学习路线
- Compose动画:Animatable、animate*AsState、Transition,页面转场动画,组件显隐动画;实际项目UI非常看重动画效果。
- 自定义布局与绘制:Modifier.drawBehind、Layout;自定义控件;画布Canvas;手写自定义图表。
- 手势处理:draggable、scroll,拖拽手势、多点触控。
- Jetpack其余组件:WorkManager后台任务;权限请求;Paging3分页加载(LazyColumn分页是业务高频需求)。
- KMP(Kotlin Multiplatform):一套Compose‑Multiplatform代码同时编译Android、桌面Windows/macOS、iOS;可以往跨平台方向深入;对比Tauri、Dioxus等Rust‑GUI。
- 测试:ViewModel单元测试;Compose UI的instrumented界面测试。
多元化习题(练习)
习题1【基础‑改错题】
开发写LazyColumn直接使用下标index当做item的key;会出现什么问题?
答案:
当删除或者插入列表中间的数据,数组下标发生变化;Lazy复用视图的时候item内容错乱,出现界面闪烁;应该使用业务实体唯一id作为key。
解读:
列表性能易错点,实战务必留意。
习题2【基础‑代码修改题】
页面一次性toast提示事件,现在已经定义好密封类ToastEffect;ViewModel内部如何发射该一次性事件?
答案:
_viewModelScope.launch {
_effect.emit(ToastEffect("操作成功"))
}
解读:
使用SharedFlow的emit;不要使用StateFlow保存一次性消息。
习题3【进阶‑补充代码题】
简单描述 collectAsState() 和 collectAsStateWithLifecycle() 的区别。
答案:
collectAsState:页面后台不可见的时候仍然持续收集数据流;会继续接收数据更新UI,浪费资源;
collectAsStateWithLifecycle:跟随页面生命周期;页面进入后台暂停收集;页面恢复之后继续收集;正式项目优先使用collectAsStateWithLifecycle。
解读:
生产环境尽量统一使用collectAsStateWithLifecycle。
习题4【综合‑逻辑应用题】
在MVI架构开发当中,为什么用户操作不直接调用ViewModel里面零散的业务函数,而是统一封装Intent,调用sendIntent(intent)?
答案:
全部交互统一走Intent之后,页面所有用户行为集中;便于统一日志埋点;方便单元测试;后续新增交互只需要新增Intent密封子类,架构风格统一。
解读:
属于工程层面的约束,小项目可以简化;中大型业务App强烈建议坚持该写法。
习题5【概念简答题】
SavedStateHandle和Room持久化二者如何分工?
答案:
SavedStateHandle:基于Bundle,保存少量临时状态;用于屏幕旋转、后台进程被杀重启恢复UI临时输入;生命周期跟随页面回退栈;卸载App之后数据消失。
Room数据库:真正本地持久化;保存业务数据笔记、列表;App重启、关机之后数据仍然保留;大量业务数据优先使用Room。
解读:
临时UI状态与业务持久化数据分开对待。
本节课知识点总结
- 复盘整套1‑13课完整知识点:基础布局‑Modifier‑状态‑副作用‑性能‑导航‑SavedStateHandle‑架构MVI‑模块化分包‑笔记实战。
- 梳理开发高频坑:状态丢失、无效重组、列表闪烁、内存泄漏、SavedStateHandle误用。
- 熟悉MVI标准开发流程;后续写业务页面可以直接参考这套流程;
- 理解单Activity架构的优势与局限,不必教条式全部页面强行单Activity;特殊SDK页面保留独立Activity。
- 指明后续进阶学习方向:动画、自定义绘制手势、Paging3分页;KMP跨平台;单元与UI测试;也可以横向对比其他GUI技术栈拓展视野。
更多推荐


所有评论(0)