一、一个让无数Android开发者头疼的老问题先看一段你可能非常熟悉的代码。假设我们要实现一个最简单的功能点击按钮让一段文字显示或隐藏。用传统XML View的方式你需要这样做在activity_main.xml里定义布局LinearLayoutandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:orientationverticalTextViewandroid:idid/messageTextandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text你好世界android:visibilityvisible/Buttonandroid:idid/toggleButtonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text隐藏//LinearLayout然后在MainActivity.kt里写逻辑classMainActivity:AppCompatActivity(){privatevarisVisibletrueoverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)valmessageTextfindViewByIdTextView(R.id.messageText)valtoggleButtonfindViewByIdButton(R.id.toggleButton)toggleButton.setOnClickListener{isVisible!isVisibleif(isVisible){messageText.visibilityView.VISIBLE toggleButton.text隐藏}else{messageText.visibilityView.GONE toggleButton.text显示}}}}这段代码能跑效果也没问题。但你有没有觉得哪里“别扭”你需要做三件事在XML里定义界面长什么样、在Kotlin里找到这些界面元素、手动告诉它们该怎么变。界面和数据是分开的两套东西你必须时刻确保它们保持一致。一旦界面变复杂——比如加载状态、错误提示、空数据页面都要处理——手动同步的工作量就会急剧膨胀。这种模式叫做命令式UI——你像指挥官一样一步一步地命令界面把文字设成什么、把按钮的可见性改为什么、把颜色换成什么。你告诉UI“怎么做”。随着视图数量增加维护复杂度也在增长。Jetpack Compose的出现就是为了从根上解决这个问题。二、Jetpack Compose是什么Jetpack Compose是Google为Android打造的现代声明式UI工具包。它用Kotlin语言编写完全抛弃了XML布局文件让你用一系列函数来描述界面。官方对它的定位非常明确Compose正在取代View工具包。传统View体系已经进入维护模式——只会收到关键的修复不会有大的功能更新。所有新的Android Studio UI工具、文档、示例代码都会优先围绕Compose来构建。这意味着什么意味着从2026年的视角来看Compose不再是“可以尝试的新东西”而是Android UI开发的默认选择。Compose的核心思想可以用一句话概括你只需要描述界面“应该是什么样”而不用操心“怎么变成这样”。回到刚才的显示/隐藏文字的例子。用Compose写大概是这个样子ComposablefunMessageToggle(){varisVisiblebyremember{mutableStateOf(true)}Column(modifierModifier.padding(16.dp)){if(isVisible){Text(text你好世界)}Button(onClick{isVisible!isVisible}){Text(textif(isVisible)隐藏else显示)}}}没有XML文件没有findViewById没有手动设置visibility。你声明了当isVisible为true时显示这段文字。当用户点击按钮isVisible变了界面自动跟着更新。这就是声明式UI的核心体验你只管描述状态和界面的关系框架负责把界面刷新到正确状态。三、命令式 vs 声明式一个生活化的比喻命令式UI和声明式UI的差别可以用一个日常场景来理解。命令式就像你指挥一个司机开车“往前开200米左转直行100米右转靠边停。”每一步你都要给出精确的指令。如果路况变了比如前方施工你得重新规划每一步。声明式就像你打开导航输入目的地然后说“我要去这里。”导航自己会算出路线、处理路况变化、在需要的时候重新规划。你只关心“我要到哪里”不关心“怎么到那里”。在传统View体系下你就是那个不停下指令的指挥者。数据变了你要手动去更新对应的View多个View显示同一份数据你就要确保每一处都更新了。一旦漏掉一处就会出现界面和数据不一致的Bug。Google的官方文档也明确指出手动操作视图会增加出错的可能性而且随着需要更新的视图数量增加维护复杂度会持续增长。在Compose的声明式模型下你只描述一件事“当状态是A时界面长这样当状态是B时界面长那样。”状态变了的瞬间Compose自动完成从状态到界面的映射。你不需要追踪哪些View需要更新不需要记住上次的状态是什么。这种思维转变是学习Compose最需要跨越的门槛。一旦习惯了你会发现UI代码变得异常简洁和可预测。四、可组合函数Compose的“基本粒子”在Compose的世界里一切界面都是由可组合函数构成的。可组合函数就是普通的Kotlin函数只不过它被一个特殊的注解标记了Composable。这个注解告诉Compose编译器“这个函数是用来描述界面的。”来看一个最简单的可组合函数ComposablefunGreeting(name:String){Text(text你好$name)}这个函数做了几件事接收数据name参数让调用者可以传入不同的名字发射UI调用Text()可组合函数在界面上显示一段文字不返回任何东西它描述的是“屏幕上应该出现什么”而不是“构造一个对象返回给你”可组合函数有几个重要的特性第一它可以调用其他可组合函数。Greeting调用了Text而Text本身也是一个可组合函数。通过这种嵌套你可以从最小的UI元素开始一层一层搭建出复杂的界面。第二它应该是“纯”的。官方文档强调可组合函数应当是幂等的——同样的输入应该得到同样的输出不依赖全局变量不产生副作用比如修改外部变量。这听起来是个限制但实际上它让Compose能够智能地判断这个函数的输入没变那它的输出也不用重新计算直接复用就行。第三函数的命名习惯用大写开头。比如Greeting、MessageCard、UserProfile这跟传统Kotlin函数用小写开头的习惯不同为的是在代码里一眼就能区分“这是UI组件”和“这是普通逻辑”。可组合函数最强大的地方在于组合。你可以把界面拆成一个个小的、独立的可组合函数每个只负责一小块。小的可以组合成大的大的可以组合成更大的。就像乐高积木一样每块积木很简单但拼在一起可以搭出任何东西。官方文档也特别提到通过制作小的可复用可组合项很容易构建起一个应用级别的UI元素库每个元素独立负责屏幕的一部分可以单独编辑和测试。五、为什么说Compose值得学五个实打实的理由5.1 代码量大幅减少刚才的显示/隐藏示例已经很直观了。在传统方式下你需要一个XML文件加一个Activity/Kotlin文件在Compose里一个函数就够了。对于更复杂的界面——比如一个带头像、名字、在线状态、操作按钮的用户卡片——XML可能需要三四十行Compose可能只需要十几行。这不是“少写一点”的问题而是代码组织方式的根本变化。XML和Kotlin逻辑是分开的你需要在两个文件之间来回跳转来理解一个界面。Compose把布局和逻辑放在同一个函数里代码的局部性更好阅读和维护都更轻松。5.2 状态驱动告别手动同步这是最核心的改变。在Compose里你不需要手动调用findViewById不需要记住哪个View绑定了哪个数据。你只需要定义状态然后说“当状态是这样的时候界面应该是那样”。当状态变化时Compose会自动找出哪些界面依赖了这个状态只重新执行那些部分。这个过程叫做重组。你不用操心“哪些View需要更新”框架帮你做了这件事。5.3 原生性能滚动流畅度已追平View早期版本的Compose在性能上确实和View有一定差距但这个问题已经基本解决了。根据Google的路线图从Compose 1.9.0开始滚动性能以卡顿为指标已经与View持平。Compose通过智能跳过机制来优化性能如果一个可组合函数的输入参数没有变化Compose会完全跳过它的重新执行直接复用之前的UI输出。这种优化在列表滚动等高频场景下效果显著。5.4 开发工具强大预览即所得Android Studio为Compose提供了专门的开发体验。Preview注解可以让你在IDE里直接看到UI的渲染效果不用把应用跑到设备上。配合实时编辑功能你改一行代码预览立刻更新。还有一个很实用的变化新的Android Studio UI工具只面向Compose构建传统的布局编辑器和导航编辑器已经不再获得新功能。5.5 自适应布局一套代码适配多种设备Compose在设计之初就考虑了自适应的问题。手机、平板、折叠屏、甚至桌面端的Android应用Compose都提供了统一的工具来适配不同屏幕尺寸。官方明确表示Compose是构建自适应应用最简单的方式。六、Compose的架构分层了解它的“内功”你不需要一开始就深入理解Compose的每一层架构但知道它的分层设计有助于你理解“为什么Compose能做到这些”。Jetpack Compose不是一个大而全的库而是由多个模块组装而成的。从底层到上层主要分为四层。最底层是Runtime运行时。这一层提供了Compose最核心的机制remember、mutableStateOf、Composable注解、状态追踪等。它管的是“状态怎么存、什么时候重组”这类底层逻辑跟具体的UI长什么样没有关系。第二层是UI层。这一层开始涉及界面了它负责布局节点的管理、Modifier系统、输入事件处理、自定义布局和绘制。Modifier是Compose里一个很重要的概念——你可以把它理解成“给一个UI元素附加的各种属性”比如内边距、背景色、点击事件等。第三层是Foundation基础层。这一层提供了与设计系统无关的构建块比如Row横向排列、Column纵向排列、LazyColumn懒加载列表、手势识别等。如果你只是想要基本的布局能力Foundation就够了。最上层是Material层。这一层是Material Design在Compose中的实现提供了主题系统、按钮、卡片、顶部栏等预制的Material组件。这个分层设计的精妙之处在于每一层都建立在下面一层之上但你可以在任何一层开始构建。如果你只需要Compose的状态管理能力可以只用Runtime层如果你想要完整的Material Design体验直接用最上层的组件就好。官方强调Compose的指导原则是提供一系列小而可组合的模块而不是几个庞大的单体组件。七、Compose与传统View的对比一张“大白话”清单把两种方式放在一起对比差异会更清楚对比维度传统XML ViewJetpack Compose界面定义方式XML文件定义布局Kotlin函数描述界面编程范式命令式手动更新View声明式状态驱动自动更新查找视图findViewById/ ViewBinding不需要直接调用可组合函数状态同步手动同步数据和界面自动重组状态变了界面跟着变布局与逻辑分开在两个文件中在同一个函数中预览布局编辑器Preview注解支持实时编辑最小API支持各版本不同API 21Android 5.0及以上组件复用自定义View较复杂可组合函数天然可复用当前状态维护模式仅关键修复Compose-first持续更新关于最小API支持Compose只需要API level 21Android 5.0及以上即可使用覆盖面已经非常广。关于“维护模式”Google明确表示View工具包如android.widget包中的TextView、ListView等现在处于维护模式只会收到高度关键的修复。传统的基于View的Jetpack库也不会获得重大更新。所有新的Android Studio UI工具只面向Compose构建。八、状态管理Compose的“引擎”状态是Compose最核心的概念之一。理解状态就理解了Compose的“引擎”是怎么工作的。8.1 一个“不工作”的例子先看一段看起来合理、但实际不会工作的代码ComposablefunGreeting(){varexpandedfalse// 这样写不对Column{Text(textif(expanded)展开的内容else)Button(onClick{expanded!expanded}){Text(if(expanded)收起else展开)}}}点击按钮expanded确实变了但界面不会更新。原因有两个第一普通的变量赋值不会被Compose追踪。Compose不知道这个变量变了自然也不会触发重组。第二即使Compose追踪了每次Greeting函数被重新执行时var expanded false都会把值重置回false状态丢失了。8.2 mutableStateOf remember要让Compose“知道”一个值的变化需要用mutableStateOf来包装它valexpandedmutableStateOf(false)mutableStateOf创建的是一个可观察的状态对象。当它的value发生变化时所有读取了这个状态的可组合函数都会被标记为“需要重新执行”。但是光用mutableStateOf还不够。因为可组合函数随时可能被重新执行重组如果每次执行都创建一个新的mutableStateOf(false)状态就丢了。所以还需要remember来帮忙valexpandedremember{mutableStateOf(false)}remember的作用是在首次组合时计算并存储一个值在后续重组中返回同一个值不重新计算。合在一起正确写法是ComposablefunGreeting(){varexpandedbyremember{mutableStateOf(false)}Column{if(expanded){Text(text展开的内容)}Button(onClick{expanded!expanded}){Text(if(expanded)收起else展开)}}}这里用了Kotlin的by委托语法读和写expanded就像操作普通变量一样实际上底层是在操作MutableState的value属性。8.3 状态提升让状态“住”在合适的地方有时候一个状态不只是一个可组合函数内部的事。比如父组件和子组件可能都需要读写同一个状态。Compose的解决办法叫状态提升把状态从子组件“提升”到它们的共同父组件中子组件通过参数接收状态值通过回调函数通知父组件状态应该怎么变。ComposablefunParent(){vartextbyremember{mutableStateOf()}Column{Child(valuetext,onValueChange{textit})Text(text你输入了$text)}}ComposablefunChild(value:String,onValueChange:(String)-Unit){TextField(valuevalue,onValueChangeonValueChange)}Child不持有状态它只负责“显示”和“通知”。状态由Parent持有。这种模式叫做单向数据流数据从父流向子事件从子流回父。官方文档指出由于可组合函数接受状态并公开事件如TextField接受值并公开onValueChange回调单向数据流模式天然适用于Jetpack Compose。状态提升的好处是状态的来源变得清晰可追溯测试起来也更容易——你不需要启动整个UI只需要给函数传入不同的参数就能测试它的行为。九、从零搭建一个Compose项目讲了这么多概念是时候动手了。9.1 环境要求Android Studio建议使用最新稳定版。Compose的开发体验高度依赖IDE工具链。KotlinCompose完全基于Kotlin需要确保项目已经配置了Kotlin支持。最小APIAPI 21Android 5.0及以上。9.2 创建项目打开Android Studio在欢迎界面点击New Project如果已经打开了项目选择File New New Project。在模板列表中选择Empty Activity。在配置界面中确保语言选择Kotlin——Jetpack Compose只支持Kotlin。创建完成后Android Studio会自动帮你配置好Compose所需的Gradle依赖和编译器插件。你不需要手动添加任何东西。9.3 看懂自动生成的代码项目创建后打开MainActivity.kt你会看到类似这样的代码classMainActivity:ComponentActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContent{MyAppTheme{Scaffold(modifierModifier.fillMaxSize()){innerPadding-Greeting(nameAndroid,modifierModifier.padding(innerPadding))}}}}}ComposablefunGreeting(name:String,modifier:ModifierModifier){Text(textHello$name!,modifiermodifier)}Preview(showBackgroundtrue)ComposablefunGreetingPreview(){MyAppTheme{Greeting(Android)}}这段代码里有几个关键点值得注意setContent这是从传统Activity世界进入Compose世界的“入口”。在setContent的lambda里你写的一切都是可组合函数。Scaffold提供了一个Material Design的基本页面结构。innerPadding用来避免内容被状态栏、导航栏等系统UI遮挡。Preview这个注解让GreetingPreview函数可以在Android Studio的预览面板中渲染出来。你不需要把应用跑到设备上就能看到Greeting组件长什么样。这是Compose开发中非常高频使用的功能。Modifier你看到Greeting函数接收了一个modifier: Modifier Modifier参数。这是Compose的惯例——每个可组合函数都应该接受一个Modifier参数这样调用者可以从外部给组件添加各种修饰内边距、尺寸、点击事件等。9.4 改一行代码试试把Greeting里的文字改掉Text(text你好Compose)保存后预览面板会立刻更新。这就是Compose开发最日常的节奏写代码看预览改代码预览更新。不需要编译、安装、启动应用。十、Compose的现状与未来10.1 现状Compose-first2026年的Android开发已经进入Compose-first时代。Google明确表示新工具只面向Compose所有新的Android Studio UI工具都只为Compose构建。文档和教程以Compose为主官方的文档、codelab、示例项目都优先围绕Compose展开。View进入维护模式传统View组件只会收到关键修复不会有新功能。但这不意味着View会立刻消失。Google也承诺会在一段时间内继续支持传统View并提供互操作API让开发者可以按自己的节奏逐步迁移。10.2 迁移路径渐进式采用如果你手上有一个基于XML和View的现有项目不需要一次性全部重写。Compose支持与View的双向互操作在View中使用Compose可以通过ComposeView把Compose界面嵌入到XML布局中。在Compose中使用View可以通过AndroidView可组合函数把传统的View嵌入到Compose界面中。推荐的迁移策略是“Compose Island”从新功能或者某个独立的页面开始用Compose实现作为一个“岛屿”嵌入到现有的View体系中。随着时间推移岛屿越来越多最终完成迁移。10.3 路线图上的亮点根据Google公布的Compose路线图未来值得关注的方向包括性能持续优化矢量缓存改进、模糊效果改进、高级图形效果文本和输入增强多样式文本编辑、文本选择API改进、自适应文字大小动画和导航更高级的动画支持、共享元素过渡生成式AI与UI开发实验将AI能力融入UI开发流程10.4 现在就是学习Compose的最佳时机如果你还在犹豫“要不要学Compose”答案已经很清楚了要。不是因为Compose“新”而是因为它已经是Android UI开发的主流方向。新项目默认用Compose新工具优先支持Compose新文档围绕Compose编写。继续只用传统View体系意味着你在使用一个处于维护模式的技术栈。而且学Compose的门槛并不高。它用Kotlin这是大多数Android开发者已经熟悉的语言。它的核心概念——可组合函数、状态、重组——数量不多而且逻辑自洽。一旦理解了“声明式思维”后面的路会越来越顺。十一、本课小结这一课我们聊了这些问题为什么需要Compose传统命令式UI在复杂界面下的维护成本越来越高声明式UI是行业的演进方向。Compose是什么一个声明式的、基于Kotlin的UI工具包你描述“界面应该是什么样”框架负责“怎么变成这样”。可组合函数Compose的基本构建单元用Composable注解标记的普通函数接收数据、发射UI。架构分层Runtime → UI → Foundation → Material从底层机制到上层组件每一层都可以独立使用。状态管理mutableStateOf创建可观察状态remember在重组间保留状态状态提升让状态在组件树中流动。环境搭建用Android Studio创建Empty Activity项目Preview可以实时预览Modifier用来修饰组件。现状与未来Compose-first已经成为Android开发的既定方向View体系逐步进入维护模式但互操作API保证了渐进式迁移的可行性。如果这一课你只记住一件事希望是这个在Compose里你不再需要告诉界面“怎么变”只需要告诉它“是什么”。状态变了界面自己会跟上。下一课我们会正式动手写Compose代码——从最基本的布局开始逐步构建出真实的界面。