30、课程总结与未来展望:Compose 生态全景,学习路线建议,常见面试题解析
终于到了最后一章。说实话,写到这里我还有点舍不得。
从第一行 setContent 开始,到如今你能用 Compose 搭建完整的页面、处理状态、做动画、甚至写自定义布局——这一路走来,你付出的时间我都懂。因为我自己也是这么过来的。
这一章我们不写新代码了。我想跟你聊聊三件事:Compose 生态到底长什么样、接下来该怎么学、以及面试官最爱问什么。嗯,算是给这段旅程画个句号,也给你指个方向。
本章核心:全景梳理 + 学习路线 + 面试实战。不灌水,只讲干货。
30.1 Compose 生态全景:你站在哪里
先看一张图。这是我整理的 Compose 生态结构,说白了就是告诉你:你现在会的东西,在整个体系里处于什么位置。
你看,你现在已经掌握了核心层和基础组件层的大部分内容。说白了,你已经能独立开发一个完整的 App 了。但如果你想进阶,就得往扩展库层和跨平台层走。
我个人习惯把 Compose 生态比作一棵树:根是 Runtime,干是 UI,枝叶是各种扩展库,而果实是跨平台。你想想看,根和干你已经摸透了,接下来就是让枝叶茂盛起来。
30.2 学习路线建议:接下来怎么走
经常有同学问我:「老师,学完这门课之后我该学什么?」
我的回答一般分三步。嗯,这三步也是我自己走过的路。
第一步:把基础打牢(1-2 个月)
- 状态管理深入:搞懂
remember、mutableStateOf、StateFlow、collectAsState的区别。我在项目中踩过最大的坑就是状态提升没做好,导致重组爆炸。 - Modifier 链式调用:别只会用
.padding()和.size()。去研究.drawBehind、.pointerInput、.graphicsLayer。这些才是 Compose 的「魔法」。 - 自定义布局:
Layout和SubcomposeLayout一定要手写一遍。我曾经为了做一个瀑布流布局,折腾了整整两天——但写完之后,对 Compose 的理解直接上了一个台阶。
第二步:掌握扩展库(2-3 个月)
- Navigation Compose:路由传参、深层链接、返回栈管理。面试必问。
- Hilt + ViewModel:依赖注入 + 生命周期感知。记住,
viewModel()在 Compose 里用起来比 Fragment 时代爽太多了。 - Coil:图片加载。配合
AsyncImage使用,注意占位图和错误处理。 - Paging 3:分页加载。配合
LazyColumn实现无限滚动。 - Room:本地数据库。配合
Flow实现响应式数据更新。
我的建议:不要一口气学完所有库。挑一个你当前项目最需要的,先学透。比如你正在做列表页,就先啃 Paging 3。学一个用一个,比学完忘光强一百倍。
第三步:挑战跨平台(3-6 个月)
- Compose Multiplatform:目前稳定支持 Android + Desktop,iOS 还在 Beta。如果你有 KMP 基础,可以试试。
- Ktor + SQLDelight:网络请求和数据库的跨平台方案。
- 共享 UI:把公共组件抽到
commonMain里,平台差异用expect/actual处理。
说实话,跨平台这块我还在探索中。但趋势很明显——Google 和 JetBrains 都在推,未来两三年会成为主流。
30.3 常见面试题解析:这些题我都被问过
下面这些题,是我在面试别人和被别人面试时,反复遇到的。我挑了几个最经典的,给你拆解一下。
30.3.1 Compose 和 View 系统的区别是什么?
考察点:对 Compose 本质的理解。
回答思路:
- View 系统是命令式的:你告诉系统「把这个 TextView 的文本改成 xxx」。
- Compose 是声明式的:你告诉系统「当状态为 xxx 时,UI 长这样」。系统自己决定怎么更新。
- Compose 没有
findViewById,没有LayoutInflater,没有RecyclerView.Adapter。一切皆 Composable。
加分项:提到 Compose 的「重组」机制——只有状态变化的部分会重新执行,而不是整个 UI 树重建。
30.3.2 什么是重组?如何避免不必要的重组?
考察点:性能优化意识。
回答思路:
- 重组就是 Compose 在状态变化时,重新执行某些 Composable 函数来更新 UI。
- 避免方法:
- 使用
remember缓存计算结果 - 使用
derivedStateOf减少不必要的状态派生 - 使用
key参数帮助 Compose 识别稳定的 Composable - 把稳定的参数用
lambda包裹,避免重组时重新创建
- 使用
我曾经踩过的坑:在 LazyColumn 的 item 里直接传了一个大对象,结果每次滑动都触发全部 item 重组。后来改成传 id 然后在 item 内部用 remember 加载数据,性能直接翻倍。
30.3.3 Compose 中如何处理生命周期?
考察点:对 Lifecycle 和 Effect 的理解。
回答思路:
- 使用
LaunchedEffect处理协程任务,它会跟随 Composable 的生命周期自动取消。 - 使用
DisposableEffect注册和清理资源(比如监听器、广播)。 - 使用
LifecycleEventEffect(来自lifecycle-runtime-compose)监听具体事件。 - 在 ViewModel 里,生命周期由
viewModelScope管理。
30.3.4 如何实现一个自定义布局?
考察点:对 Layout 和 MeasurePolicy 的掌握。
回答思路:
- 使用
Layout可组合项,传入content和measurePolicy。 - 在
MeasurePolicy.measure里,先测量所有子元素,然后根据需求放置它们。 - 示例:实现一个简单的「流式布局」,子元素从左到右排列,排不下就换行。
@Composable
fun FlowLayout(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Layout(
modifier = modifier,
content = content
) { measurables, constraints ->
val placeables = measurables.map { it.measure(constraints) }
var x = 0
var y = 0
val rowHeight = placeables.maxOf { it.height }
layout(constraints.maxWidth, constraints.maxHeight) {
placeables.forEach { placeable ->
if (x + placeable.width > constraints.maxWidth) {
x = 0
y += rowHeight
}
placeable.placeRelative(x, y)
x += placeable.width
}
}
}
}
30.3.5 Compose 和 View 如何混合使用?
考察点:迁移策略和互操作性。
回答思路:
- 在 Compose 中使用 View:
AndroidView包裹。 - 在 View 中使用 Compose:
ComposeView作为容器。 - 注意生命周期和状态同步,避免内存泄漏。
我的经验:如果项目是逐步迁移,建议从「叶子节点」开始——先替换最小的 UI 组件(比如一个 Button 或 Card),再慢慢往上替换页面。不要一上来就重构整个 Activity,容易翻车。
30.4 写在最后:保持好奇,保持动手
课程到这里就结束了。但你的 Compose 之旅,才刚刚开始。
我记得自己刚学 Compose 时,也觉得很别扭——怎么没有 XML?怎么没有 findViewById?但当我真正理解了「状态驱动 UI」这个思想后,就再也回不去了。
你想想看,从 2019 年 Compose 发布第一个预览版,到现在成为 Android 开发的主流方案,才不过四五年时间。这个生态还在飞速发展:Compose Multiplatform 正在成熟、Material Design 3 在迭代、新的动画 API 在涌现。
所以我的建议很简单:保持好奇,保持动手。遇到不懂的,去翻源码、去写 Demo、去社区提问。别怕犯错——我写 Compose 两年多了,照样会踩坑。但每踩一个坑,就离「高手」更近一步。
最后,送你一句话:「Compose 不是终点,而是 Android 开发的新起点。」
加油,我们江湖再见。
公众号:蓝海资料掘金营,微信 deep3321