首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >[Android 从零到一] Jetpack Compose 入门:用声明式 UI 写 Android 页面

[Android 从零到一] Jetpack Compose 入门:用声明式 UI 写 Android 页面

原创
作者头像
hunter android
修改2026-06-25 17:20:32
修改2026-06-25 17:20:32
1120
举报

背景

过去写 Android 页面,主流方式是 XML 布局加 Activity/Fragment 代码:XML 负责描述控件层级,Kotlin/Java 负责查找 View、绑定数据、处理点击。这套模式稳定,但页面复杂后很容易出现两个问题:一是 UI 结构和状态逻辑分散在不同文件里,阅读成本高;二是状态变化后要手动更新多个 View,遗漏一个就会出现界面不同步。

核心概念

Composable 函数

被 `@Composable` 标记的函数就是一个 UI 片段。它可以像普通 Kotlin 函数一样接收参数、组合调用,但只能在另一个 Composable 环境中执行。可以把它理解成“用函数声明控件树”。

声明式 UI

传统 View 更偏命令式:先找到按钮,再调用 `button.text = ...`、`button.visibility = ...`。Compose 更偏声明式:你只描述“当状态为 A 时显示什么,当状态为 B 时显示什么”。状态一变,Compose 会触发重组(Recomposition),自动更新界面。

State 与 remember

`remember` 用于在重组之间保存对象,`mutableStateOf` 用于创建可观察状态。只要 Composable 读取了某个 State,当它变化时,相关 UI 就会自动刷新。

Modifier

`Modifier` 是 Compose 中非常重要的修饰链,用来设置大小、间距、背景、点击、滚动等行为。它不是传统 View 的属性集合,而是一条从左到右顺序生效的链。

Kotlin 代码实战

先确保模块启用了 Compose,并引入基础依赖。新版本 Android Studio 创建 Empty Activity 时可以直接选择 Compose 模板,这里重点看代码结构。

1. 在 Activity 中挂载 Compose

代码语言:javascript
复制
import android.os.Bundle

import androidx.activity.ComponentActivity

import androidx.activity.compose.setContent

import androidx.compose.material3.MaterialTheme

import androidx.compose.material3.Surface



class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContent {

            MaterialTheme {

                Surface {

                    CounterScreen()

                }

            }

        }

    }

}

`setContent {}` 取代了过去的 `setContentView(R.layout.xxx)`。花括号内部就是 Compose 世界,后续页面都从这里组合出来。

2. 写一个简单计数页面

代码语言:javascript
复制
import androidx.compose.foundation.layout.Arrangement

import androidx.compose.foundation.layout.Column

import androidx.compose.foundation.layout.Row

import androidx.compose.foundation.layout.Spacer

import androidx.compose.foundation.layout.fillMaxSize

import androidx.compose.foundation.layout.height

import androidx.compose.foundation.layout.padding

import androidx.compose.material3.Button

import androidx.compose.material3.Text

import androidx.compose.runtime.Composable

import androidx.compose.runtime.getValue

import androidx.compose.runtime.mutableIntStateOf

import androidx.compose.runtime.remember

import androidx.compose.runtime.setValue

import androidx.compose.ui.Alignment

import androidx.compose.ui.Modifier

import androidx.compose.ui.unit.dp

import androidx.compose.ui.unit.sp



@Composable

fun CounterScreen() {

    var count by remember { mutableIntStateOf(0) }



    Column(

        modifier = Modifier

            .fillMaxSize()

            .padding(24.dp),

        verticalArrangement = Arrangement.Center,

        horizontalAlignment = Alignment.CenterHorizontally

    ) {

        Text(text = "当前计数:$count", fontSize = 24.sp)



        Spacer(modifier = Modifier.height(16.dp))



        Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {

            Button(onClick = { count-- }) {

                Text("减一")

            }

            Button(onClick = { count++ }) {

                Text("加一")

            }

        }

    }

}

这段代码里没有 `findViewById`,也没有手动设置 TextView 文本。`count` 改变后,读取 `count` 的 `Text` 会自动刷新,这就是状态驱动 UI 的直观体现。

3. 拆分可复用组件

实际项目不要把所有内容都塞进一个函数。可以把展示区和按钮区拆出来,让页面更容易测试和维护。

代码语言:javascript
复制
@Composable

fun CounterTitle(count: Int) {

    Text(text = "当前计数:$count", fontSize = 24.sp)

}



@Composable

fun CounterActions(

    onDecrease: () -> Unit,

    onIncrease: () -> Unit

) {

    Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {

        Button(onClick = onDecrease) { Text("减一") }

        Button(onClick = onIncrease) { Text("加一") }

    }

}

调用方只传状态和事件,不把内部实现暴露出去:

代码语言:javascript
复制
@Composable

fun CounterScreen() {

    var count by remember { mutableIntStateOf(0) }



    Column(

        modifier = Modifier.fillMaxSize().padding(24.dp),

        verticalArrangement = Arrangement.Center,

        horizontalAlignment = Alignment.CenterHorizontally

    ) {

        CounterTitle(count = count)

        Spacer(modifier = Modifier.height(16.dp))

        CounterActions(

            onDecrease = { count-- },

            onIncrease = { count++ }

        )

    }

}

4. 列表写法

Compose 中列表通常使用 `LazyColumn`,它类似 RecyclerView,只渲染当前屏幕附近的内容。

代码语言:javascript
复制
import androidx.compose.foundation.lazy.LazyColumn

import androidx.compose.foundation.lazy.items



@Composable

fun MessageList(messages: List<String>) {

    LazyColumn {

        items(messages) { message ->

            Text(

                text = message,

                modifier = Modifier.padding(16.dp)

            )

        }

    }

}

如果列表项有稳定 ID,建议加 `key`,减少重组和滚动状态错乱:

代码语言:javascript
复制
items(

    items = messages,

    key = { it }

) { message ->

    Text(text = message, modifier = Modifier.padding(16.dp))

}

避坑指南

不要在 Composable 里直接执行耗时操作。 Composable 可能因为状态变化反复重组,如果在函数体里直接请求网络、读数据库或写文件,就可能被重复执行。副作用逻辑应放到 ViewModel,或使用 `LaunchedEffect`、`DisposableEffect` 等 Compose 副作用 API。

remember 不是持久化。 `remember` 只能在当前组合生命周期内保存状态,Activity 重建后可能丢失。需要应对旋转屏幕、进程恢复时,用 `rememberSaveable`;需要业务状态共享时,用 ViewModel。

Modifier 顺序会影响结果。 `Modifier.padding().background()` 和 `Modifier.background().padding()` 的视觉效果不同。前者是先留白再画背景,后者是先画背景再留白。遇到布局异常时,优先检查 Modifier 链顺序。

避免把可变集合直接当状态。 如果用 `mutableListOf()` 后只执行 `add()`,Compose 未必知道列表变了。更推荐使用不可变列表:`messages = messages + newMessage`,或者使用 `SnapshotStateList`。

Composable 函数保持轻量。 一个函数既处理业务、又拼 UI、还发埋点,会很快失控。推荐状态上提:页面函数接收 `uiState` 和事件回调,业务逻辑放在 ViewModel 中。

Compose 与 XML 可以共存。 老项目没必要一次性重写。可以在 XML 中用 `ComposeView` 嵌入 Compose,也可以在 Compose 里用 `AndroidView` 包一段传统 View,逐步迁移更安全。

总结

Jetpack Compose 的入门关键不在于记住多少控件,而是转变思维:界面由状态描述,事件改变状态,状态再驱动界面刷新。掌握 `@Composable`、`remember`、`State`、`Modifier` 和 `LazyColumn` 后,就已经能写出常见页面。

如果是新项目,可以优先使用 Compose;如果是存量项目,建议从独立页面、设置页、空状态页、列表 Item 开始试点。Compose 降低了 UI 开发的模板成本,但也要求我们更认真地管理状态和副作用。把这两点做好,声明式 UI 会让 Android 页面开发轻很多。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 核心概念
    • Composable 函数
    • 声明式 UI
    • State 与 remember
    • Modifier
  • Kotlin 代码实战
    • 1. 在 Activity 中挂载 Compose
    • 2. 写一个简单计数页面
    • 3. 拆分可复用组件
    • 4. 列表写法
  • 避坑指南
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档