Jetpack Compose:是什么、核心概念及composable函数

作者: IT Sectr 发布日期: 2026-05-01 阅读时间: 9 分钟

Jetpack Compose是一个现代声明式工具包,用于在Kotlin中构建Android界面。开发人员通过composable函数描述UI,工具包会自动仅重绘已更改的部分。根据Android Developers (2026),Jetpack Compose可在Android 5.0(API 21)及以上版本运行,支持Material Design 3,并凭借其自身的Recomposition系统——一种仅更新已更改小部件的智能diff算法——在中端设备上达到120 FPS。

要点

  • Jetpack Compose——Android的声明式UI框架,通过Kotlin中的@Composable注解函数构建界面。
  • Recomposition——仅自动更新数据已更改的组件的机制,确保120 FPS。
  • State通过mutableStateOf、collectAsState和StateFlow管理——值更改时,组合会为依赖的视图重启。
  • Modifier——用于配置间距、尺寸、背景、点击和动画的函数链,无需类继承。
  • Side Effects——LaunchedEffect、DisposableEffect和rememberCoroutineScope——管理副作用:定时器、网络请求、订阅。

什么是Jetpack Compose?

Jetpack Compose——是Google推出的用于构建Android用户界面的声明式框架,于2019年发布,2021年达到稳定版本。与旧的View System(XML + Activity/Fragment)不同,Compose使用带注解的Kotlin函数——@Composable。界面完全用Kotlin描述:XML和代码之间没有分离。这消除了与XML和Kotlin中id不匹配相关的一类错误(type-safe synthetic在重构时无济于事)。

Compose构建在自有渲染系统——Canvas之上,不绑定到View层次结构。每个Composable直接在Canvas上绘制,绕过View System的onMeasure/onDraw。这在复杂屏幕上带来了性能提升:在Google的测试(2023)中,包含200个元素的Compose屏幕比RecyclerView + ViewHolder上的类似屏幕快40%。

最低要求和兼容性

Compose工作需要minSdk 21(Android 5.0)和Kotlin 1.9+。Compose BOM(Bill of Materials)同步所有Compose库的版本。该框架与View System上的现有代码兼容:Compose通过ComposeView嵌入XML,旧View通过AndroidView嵌入Compose层次结构。根据Google Play Console(2025)的数据,Android 5.0+覆盖了97%的活跃设备,因此兼容性对大多数项目来说不是限制。

Composable函数与组合

@Composable——是一个注解,将普通的Kotlin函数转换为UI构建块。Composable函数描述界面片段——文本、按钮、列表——的外观。该函数不返回值,而是将UI组件发射到组合中。这类似于生成器:每个函数在调用时向屏幕添加元素。

kotlin
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
    Card(
        modifier = Modifier.fillMaxWidth().padding(16.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surface
        )
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            AsyncImage(
                model = avatarUrl,
                contentDescription = "头像",
                modifier = Modifier.size(48.dp).clip(CircleShape)
            )
            Spacer(Modifier.width(12.dp))
            Text(
                text = name,
                style = MaterialTheme.typography.titleMedium
            )
        }
    }
}

ProfileCard函数接收参数(name, avatarUrl)并发射Card → Row → AsyncImage + Text。组合——是一次传递中已发射组件的树。如果参数没有更改,Compose会跳过函数调用(recomposition skip)。如果仅name发生更改,则仅调用Text,其他元素不会重绘。这种intelligent recomposition——是Compose相对于View System手动优化的关键性能优势。

Slot与Content Lambda

Composable函数积极使用slot——trailing lambda,content: @Composable (() -> Unit)。这允许创建容器:Card、Column、Row接收content lambda,内容嵌入到slot位置。Slot API取代了android:layout_gravity等XML属性——现在子元素的位置由content块内的Kotlin代码确定。

Compose中的状态管理

状态在Compose中——是任何可以随时间变化的值。当状态更改时,Compose会为读取此状态的所有组件计划recomposition。该机制类似于React hooks:mutableStateOf返回MutableState,读取.value会自动将当前组合订阅到更改。

kotlin
@Composable
fun CounterExample() {
    var count by remember { mutableStateOf(0) }

    Column(modifier = Modifier.padding(16.dp)) {
        Text("已按下:$count")
        Button(onClick = { count++ }) {
            Text("增加")
        }
    }
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val userName by viewModel.userName.collectAsState()
    Text("用户:$userName")
}

remember在重新组合之间保持值——否则mutableStateOf会在每次UI更新时重新创建。collectAsState()将ViewModel中的StateFlow转换为Compose兼容的状态。建议——对于屏幕状态使用ViewModel与StateFlow,对于局部状态(例如展开的卡片)使用mutableStateOf。这种分离符合"智能/笨拙"组件的原则。

State Hoisting

State Hoisting——将状态从子组件提升到父组件的模式。父组件通过参数传递值和回调,子组件在更改时调用回调。父组件存储mutableStateOf,子组件仅存储参数。这使得组件可重用和可测试:同一个TextField可以与任何数据源一起使用。

Modifier——外观配置

Modifier——是描述Composable变换的对象:大小、间距、背景、点击处理、动画、滚动。修饰符通过调用链应用:Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }。每次调用返回一个带有添加属性的新Modifier——不改变原始对象。

修饰符的顺序很重要。Modifier.padding(16.dp).background(Color.Blue)绘制带间距的区域。Modifier.background(Color.Blue).padding(16.dp)绘制内部矩形,间距保持透明。机制类似于CSS box模型:padding → background像margin + background一样工作;background → padding——像内部background + padding。开发人员只需记住:padding先 = 外部间距,padding后 = 内部。

自定义修饰符

如果内置修饰符不够,可以通过Modifier.composed { ... }Modifier.then()创建自定义修饰符。在自定义修饰符内部,可以使用布局测量(Modifier.layout { measurable, constraints -> ... })、绘制(Modifier.drawWithContent { ... })、手势(Modifier.pointerInput { ... })。示例:用于按下时脉冲动画的修饰符——测量尺寸,点击时通过animateFloatAsState启动缩放动画。

对于动画,Compose提供animate*AsState(animateFloatAsState、animateColorAsState、animateDpAsState)——值在更改时在旧状态和新状态之间进行动画。如果需要显示/消失动画——AnimatedVisibilityAnimatedContent带有内置过渡(fade、slide、expand)。所有动画在graphics layer上工作,不会导致不必要的组合。

Side Effects:LaunchedEffect、DisposableEffect、remember

Composable函数不应直接执行副作用(网络请求、定时器、订阅)——它们在每次重新组合时被调用,这会导致请求重复。对于副作用,Compose提供Effect函数家族:LaunchedEffect在进入组合时启动协程并在退出时取消,DisposableEffect——用于需要显式清理的资源(传感器、BroadcastReceiver)。

kotlin
@Composable
fun SensorReader() {
    val context = LocalContext.current
    var sensorValue by remember { mutableStateOf(0f) }

    DisposableEffect(Unit) {
        val sensor = registerSensorListener(context) { value ->
            sensorValue = value
        }
        onDispose {
            unregisterSensorListener(sensor)
        }
    }

    Text("值:$sensorValue")
}

@Composable
fun UserGreeting(userId: String) {
    LaunchedEffect(userId) {
        val profile = api.fetchProfile(userId)
        // 状态更新
    }
}

LaunchedEffect(userId)如果userId更改则重新启动——先前的协程被取消,新的协程以新的userId启动。这消除了手动管理请求取消的问题。DisposableEffect(Unit)——具有固定键Unit的效果,在进入组合时触发,在退出时调用onDispose。SensorReader注册监听器并在离开屏幕时取消订阅——无内存泄漏风险。

rememberCoroutineScope

如果协程需要不是在进入组合时启动,而是在事件(按钮按下)时启动,则使用rememberCoroutineScope()。它返回绑定到Composable生命周期的CoroutineScope,不需要DisposableEffect。示例:在点击按钮时启动网络请求——scope.launch { viewModel.loadData() }。

Jetpack Compose与View System对比

Compose和View System之间选择——是2026年Android开发人员的主要架构问题。两种技术都得到Google的支持,但Compose是Google投入资源的主要方向。View System仅接收关键修复,不再发展。差异体现在语法、状态管理、性能和开发时间上。

方面Jetpack ComposeView System
UI描述Kotlin @Composable函数XML + Activity/Fragment
状态mutableStateOf、StateFlow、自动重绘findViewById,手动:setText、notifyDataSetChanged
性能Intelligent recomposition、Canvas渲染View层次结构、measure/layout/draw
动画animate*AsState、AnimatedVisibility、内置ValueAnimator、ObjectAnimator、Transition
兼容性minSdk 21、ComposeView/AndroidView桥接所有版本
APK大小Compose增加3-5 MB无额外开销

对于新项目,Google推荐Jetpack Compose作为UI开发标准。View System保留用于支持2021年之前编写的代码以及需要最小APK大小的情况(例如,针对入门级设备的新兴市场)。Compose凭借声明式语法和内置动画,将UI代码量比View System减少30-50%。

常见问题

我可以在现有的View System项目中使用Compose吗?

可以,通过XML中的ComposeView。添加对Compose的依赖,并将屏幕或其部分包装在ComposeView { MyComposable() }中。迁移逐个屏幕进行。

为什么我的Composable重绘过于频繁?

原因——状态提升过高或使用了可变对象。修复:对于派生数据使用derivedStateOf,对于稳定引用使用remember

如何在Compose中实现列表?

使用LazyColumn(类似于RecyclerView)。元素在滚动时创建和重用。对于具有不同单元格类型的复杂列表——LazyColumn { items(items, key = { it.id }) { ... } }

在Compose之前需要学习View System吗?

不需要,可以直接从Compose开始。了解View System有助于维护旧代码,但Compose是一个独立的生态系统,拥有自己的文档和模式。

Compose支持Material 3吗?

支持,Material 3——是自2023年以来Compose的默认主题。通过implementation(“androidx.compose.material3:material3”)连接。Material 2被视为已过时。

总结

  • Jetpack Compose——Android的声明式UI框架,整个界面通过@Composable函数用Kotlin编写。
  • Recomposition自动仅重绘已更改的组件,无需手动优化即可确保120 FPS。
  • 状态通过mutableStateOf、collectAsState和StateFlow管理;State Hoisting模式使组件可重用。
  • Modifier——用于配置外观、动画和行为的变换链,无需类继承。
  • Side Effects(LaunchedEffect、DisposableEffect)将副作用与重新组合隔离,防止内存泄漏和请求重复。
  • LazyColumn用更少的代码替代RecyclerView,AnimatedVisibility替代复杂的Animator链。
  • Google推荐所有新项目使用Compose;View System保留用于旧代码支持以及最小APK大小至关重要的情况。

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

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

讨论项目

另请阅读