30、课程总结与未来展望:Compose 生态全景,学习路线建议,常见面试题解析

终于到了最后一章。说实话,写到这里我还有点舍不得。

从第一行 setContent 开始,到如今你能用 Compose 搭建完整的页面、处理状态、做动画、甚至写自定义布局——这一路走来,你付出的时间我都懂。因为我自己也是这么过来的。

这一章我们不写新代码了。我想跟你聊聊三件事:Compose 生态到底长什么样接下来该怎么学、以及面试官最爱问什么。嗯,算是给这段旅程画个句号,也给你指个方向。

本章核心:全景梳理 + 学习路线 + 面试实战。不灌水,只讲干货。


30.1 Compose 生态全景:你站在哪里

先看一张图。这是我整理的 Compose 生态结构,说白了就是告诉你:你现在会的东西,在整个体系里处于什么位置

Jetpack Compose 生态全景图 核心层:Compose Runtime + Compose UI @Composable · Modifier · 重组 · 状态管理 · 布局系统 · 绘制 基础组件层:Material Design 3 + Foundation Scaffold · TopAppBar · Button · Card · TextField · LazyColumn 扩展库层:官方 + 社区 Navigation · Hilt · Coil · Room · Paging · Accompanist · Vico 跨平台层:Compose Multiplatform Android · iOS · Desktop · Web(实验性)

你看,你现在已经掌握了核心层基础组件层的大部分内容。说白了,你已经能独立开发一个完整的 App 了。但如果你想进阶,就得往扩展库层跨平台层走。

我个人习惯把 Compose 生态比作一棵树:根是 Runtime,干是 UI,枝叶是各种扩展库,而果实是跨平台。你想想看,根和干你已经摸透了,接下来就是让枝叶茂盛起来。


30.2 学习路线建议:接下来怎么走

经常有同学问我:「老师,学完这门课之后我该学什么?」

我的回答一般分三步。嗯,这三步也是我自己走过的路。

第一步:把基础打牢(1-2 个月)

  • 状态管理深入:搞懂 remembermutableStateOfStateFlowcollectAsState 的区别。我在项目中踩过最大的坑就是状态提升没做好,导致重组爆炸。
  • Modifier 链式调用:别只会用 .padding().size()。去研究 .drawBehind.pointerInput.graphicsLayer。这些才是 Compose 的「魔法」。
  • 自定义布局LayoutSubcomposeLayout 一定要手写一遍。我曾经为了做一个瀑布流布局,折腾了整整两天——但写完之后,对 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 中如何处理生命周期?

考察点:对 LifecycleEffect 的理解。

回答思路

  • 使用 LaunchedEffect 处理协程任务,它会跟随 Composable 的生命周期自动取消。
  • 使用 DisposableEffect 注册和清理资源(比如监听器、广播)。
  • 使用 LifecycleEventEffect(来自 lifecycle-runtime-compose)监听具体事件。
  • 在 ViewModel 里,生命周期由 viewModelScope 管理。

30.3.4 如何实现一个自定义布局?

考察点:对 LayoutMeasurePolicy 的掌握。

回答思路

  • 使用 Layout 可组合项,传入 contentmeasurePolicy
  • 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