Jetpack Compose:基础、Composable函数和State

作者: IT Sectr 发布日期: 2026-02-21 阅读时间: 8 分钟

Jetpack Compose — Google为Android开发打造的现代声明式UI框架,于2021年7月发布稳定版1.0。Compose用带有@Composable注解的Kotlin函数替代了命令式XML标记和View系统。根据Google I/O(2025)数据,Compose在55%的新Android项目中使用,UI代码平均大小相比XML减少30–50%。框架在State变化时自动仅重绘屏幕变化部分,无需手动调用notifyDataSetChanged或findViewById。

要点

  • Jetpack Compose — Google为Android打造的声明式UI框架,基于Kotlin(@Composable函数代替XML标记)。
  • @Composable — 描述UI部分的函数注解,可接受参数和读取State。
  • State和MutableState — 反应机制:State变化时,Compose仅重新启动(recompose)依赖的Composable函数。
  • remember — 在重组之间缓存值的函数;没有它,State会在每次更新时重置。
  • Modifier — 设置链(padding、size、clickable、background),管理Composable的外观和行为。

什么是Jetpack Compose?

Jetpack Compose — Google基于反应式编程原理构建的UI框架。开发者通过带有@Composable注解的Kotlin函数描述界面,而非使用带有XML布局的Activity、FragmentManager和ViewBinding。Compose不使用LayoutInflater — UI是纯Kotlin函数,编译为字节码。框架由多个库组成:Compose UI(基础组件Text、Button、Column、Row)、Compose Foundation(Material Design、手势、焦点)、Compose Material3(带Dynamic Colors的Material You)和Compose Runtime(State、Side Effects、Coroutines)。Compose运行于Android API 21+(Android 5.0),并通过ComposeView(AndroidView适配器)与现有View/XML代码完全兼容。

Compose vs View System

View System(2008)使用带有手动管理的View对象层次结构:开发者创建XML布局,通过findViewById查找View,为RecyclerView实现Adapter,并在数据变化时调用notifyDataSetChanged。Compose函数式地描述UI:状态变化时,框架仅重新启动(recompose)变化的Composable函数,计算差异并将最小更改应用于Canvas。Compose的性能与View System相当,在复杂列表(LazyColumn)场景中,通过key参数跳过不必要元素,常常优于RecyclerView。在IT Sectr,Compose用于minSdk 24+的Android应用程序新模块。

Composable函数:UI构建块

@Composable — 将普通Kotlin函数转换为UI构建块的注解。Composable函数可以调用其他Composable函数,形成组件树。与View不同,Composable函数默认没有状态——它们是stateless的,并在每次输入参数或State变化时重新绘制。编译器(Compose Compiler)将@Composable函数转换为可中断和恢复的代码(positional memoization)——这使得Compose无需完全重建树即可重新启动仅变化的部分。

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun UserProfile(name: String, avatarUrl: String) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        AsyncImage(
            model = avatarUrl,
            contentDescription = "User avatar",
            modifier = Modifier.size(48.dp)
        )
        Spacer(modifier = Modifier.width(12.dp))
        Text(
            text = name,
            style = MaterialTheme.typography.titleMedium
        )
    }
}

UserProfile函数接受name和avatarUrl作为参数,构建包含头像和名称的行。Modifier.fillMaxWidth()将组件拉伸到全宽,.padding(16.dp)添加间距。MaterialTheme.typography.titleMedium使用Material 3系统样式。当name或avatarUrl参数变化时,Compose重新启动UserProfile——用新值重新创建组件。

Jetpack Compose中的State和Recomposition

State在Compose中——任何变化会导致依赖的@Composable函数重组(重新启动)的值。基本方式是mutableStateOf(),创建带有Compose快照系统支持的MutableState<T>。Snapshot——跟踪变化的机制:写入State时,Compose将当前Snapshot标记为脏,重组调度器仅重新启动读取该State的Composable函数。对于可观察集合,使用mutableStateListOf()和mutableStateMapOf()。Compose通过collectAsState()(用于Kotlin Flow)和observeAsState()(用于LiveData)支持来自Lifecycle-Aware组件的State。

kotlin
@Composable
fun LikeButton() {
    var liked by remember { mutableStateOf(false) }
    var count by remember { mutableStateOf(42) }
    
    Button(
        onClick = {
            liked = !liked
            if (liked) count++ else count--
        },
        colors = ButtonDefaults.buttonColors(
            containerColor = if (liked) MaterialTheme.colorScheme.primary
                else MaterialTheme.colorScheme.surfaceVariant
        )
    ) {
        Text("♥ $count")
    }
}

代码创建了一个带有liked(Boolean)和count(Int)状态的「Like」按钮,通过mutableStateOf()存储。点击时,liked反转,计数器增加/减少——Compose自动重新启动LikeButton。by委托允许像普通变量一样使用State:liked = !liked而不是liked.value = !liked.value。按钮颜色在primary(已赞)和surfaceVariant(未赞)之间反应式变化。

remember:重组间缓存

remember — 在重组之间缓存值的Compose函数。没有remember,每次重启Composable函数都会创建新状态(mutableStateOf)——这会破坏应用程序逻辑:屏幕旋转或父State变化时,计数器将重置。remember接受计算器lambda,仅在首次组合时计算值;后续返回缓存结果。要重置缓存,使用remember(key)——键确定何时重新计算值。remember(key1, key2)在任一键变化时重新计算。对于长生命周期状态(能承受屏幕旋转),使用rememberSaveable——通过SavedStateHandle在Bundle中保存的remember类似物。

kotlin
@Composable
fun TimerScreen() {
    var seconds by rememberSaveable { mutableStateOf(0) }
    
    LaunchedEffect(Unit) {
        while (true) {
            delay(1000)
            seconds++
        }
    }
    
    Column(
        modifier = Modifier.fillMaxSize().padding(32.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            text = "已过时间:${seconds}s",
            style = MaterialTheme.typography.displayMedium
        )
    }
}

rememberSaveable在屏幕旋转(配置变化)时保持seconds。LaunchedEffect启动一个协程,每秒增加seconds。在TimerScreen重组(每秒)时,由于rememberSaveable,seconds不会重置。对于不应承受配置变化的状态(例如动画标志),使用普通的remember。

Modifier:Composable设置链

Modifier — 不可变容器对象,实现Builder模式用于设置Composable组件的外观、行为和布局。每次调用Modifier方法(.padding()、.width()、.clickable()、.background())都会返回一个添加了新元素的新Modifier。修饰符顺序很重要:.padding(16.dp).clickable { }——间距在点击处理程序之前应用,clickable考虑间距跟踪整个区域。.clickable { }.padding(16.dp)——间距之前的整个区域可点击,间距将内容向内移动。Modifier通过then(otherModifier)支持自定义实现,通过compositionLocal访问父级设置。

kotlin
@Composable
fun CardExample() {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
            .clickable { println("卡片已点击") },
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surfaceVariant
        )
    ) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text("Jetpack Compose", style = MaterialTheme.typography.titleLarge)
            Spacer(modifier = Modifier.height(8.dp))
            Text(
                "使用State和Modifier的Android声明式UI",
                style = MaterialTheme.typography.bodyMedium
            )
        }
    }
}

CardExample演示了Modifier链:fillMaxWidth + padding + clickable。Card — 带有自定义elevation和colors设置的Material3组件。嵌套的Column具有16dp的内边距。Compose Material3在Android 12+上自动将颜色适配到Dynamic Color(Material You)。Card是Compose中30多个内置Material3组件之一。

State hoisting和Compose架构

State hoisting — 从Composable函数向其调用者提升状态的模式,使函数变为stateless。Stateless组件通过参数接收数据和回调,不拥有自己的State。这提高了可重用性和可测试性:可以用不同State调用组件并在预览中测试。Google推荐架构:ViewModel + StateFlow(或MutableStateFlow)+ Compose中的collectAsState()。ViewModel将状态提升到屏幕级别,Compose显示。副作用(LaunchedEffect、DisposableEffect)处理一次性事件。

组件职责技术
ViewModel存储State,业务逻辑StateFlow, MutableStateFlow
Screen Composable屏幕组织,State hoistingcollectAsState(), Scaffold, LazyColumn
Stateless Component无状态UI,纯显示@Composable参数 + lambda
Side Effect一次性操作(snackbar,导航)LaunchedEffect, SnackbarHostState

常见问题

Jetpack Compose与XML布局有何不同?

XML布局是命令式的:LayoutInflater加载XML,findViewById查找View,开发者手动更新文本/列表。Compose是声明式的:UI通过Kotlin @Composable函数描述,框架在State变化时自动仅重绘变化的部分。Compose减少UI代码量30–50%且不使用XML。

Compose是否需要单独的导航库?

是的,Google提供了Navigation Compose——用于在屏幕之间进行声明式导航的库。NavController管理路由栈,composable()注册屏幕,navArgument传递参数。替代方案:Voyager(社区)和Decompose(Badoo)。Navigation Compose是官方标准,支持deep links和type-safe参数。

Jetpack Compose中的Modifier是什么?

Modifier — 应用于Composable组件的样式模式的不可变容器(padding、size、clickable、background、border、clip)。每次调用返回添加了新元素的新Modifier。顺序很重要:.padding().clickable()在点击前应用间距,.clickable().padding()则相反。Modifier是自定义Compose组件的主要方式。

Compose能在所有Android版本上运行吗?

Jetpack Compose通过Compose Compiler和Compose BOM支持Android API 21+(Android 5.0 Lollipop)。Material 3(Dynamic Colors)在Android 12+上可用;较旧版本使用回退调色板。对于新项目,Apple建议minSdk 24+(Android 7.0),Compose完全覆盖。

如何测试Compose组件?

Google提供Compose UI Test——用于在JVM(桌面)和模拟器上测试的库。主要功能:composeTestRule.setContent { }渲染组件,onNodeWithText()搜索元素,performClick()/performTextInput()进行操作。Espresso测试通过ComposeTestRule与Compose兼容,但Compose UI Test是更优且更快的方案。

总结

  • Jetpack Compose — Google为Android打造的声明式UI框架,使用Kotlin @Composable函数代替XML(自2021年稳定)。
  • @Composable — 将Kotlin函数转换为UI组件的注解;Composable函数树替代了View层次结构。
  • State和mutableStateOf — 通过Snapshot系统实现Compose反应式的基础;重组仅影响依赖函数。
  • remember在重组间缓存值;rememberSaveable在配置变化时保持State。
  • Modifier — 设置链(padding、size、clickable、background)形成不可变容器;修饰符顺序很重要。
  • State hoisting — 为stateless组件提升状态的模式;ViewModel + StateFlow + collectAsState() — 推荐架构。
  • Material 3 with Dynamic Colors(Android 12+)— Compose默认主题,自动适配设备壁纸。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读