✅ 一、Jetpack Compose 是什么?
Jetpack Compose 是 Google 推出的现代声明式 UI 工具包,用于构建 Android 原生界面。它使用 Kotlin 语言,无需 XML 布局文件,通过函数调用的方式描述界面。
🧰 二、开发环境准备
- 安装 Android Studio(建议使用最新版)
- 创建新项目时选择 “Empty Compose Activity”
- 最低支持 API 21(Android 5.0)
Compose 仅支持 Kotlin,确保项目语言设置为 Kotlin。
🧱 三、Compose 基础概念
1. 可组合函数(Composable)
使用 @Composable 注解的函数,用于定义 UI 元素。
@Composable
fun Greeting(name: String) {
Text(text = "Hello, $name!")
}
2. 预览函数(Preview)
使用 @Preview 注解可在 Android Studio 中实时预览 UI。
@Preview(showBackground = true)
@Composable
fun PreviewGreeting() {
Greeting("Compose")
}
🧪 四、状态管理(State)
Compose 使用 remember 和 mutableStateOf 来管理局部状态:
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("点击了 $count 次")
}
}
📦 五、布局组件
| 组件 | 功能说明 |
|---|---|
Column | 垂直排列子组件 |
Row | 水平排列子组件 |
Box | 层叠布局 |
LazyColumn | 类似 RecyclerView 的列表 |
Column {
Text("第一行")
Text("第二行")
}
🎨 六、Material Design 支持
Compose 内置 Material3 组件库,常用组件包括:
ButtonTextFieldCardScaffold(页面骨架)
七、基本配置
1. 工程级配置(一次性搞定)
1.1 版本管理:使用 Compose BOM
Google 每月发布 Compose BOM(Bill of Materials),一次性锁定 一组经过测试的 Compose 版本号,避免“版本地狱”。
// libs.versions.toml(Version Catalog 风格)
[versions]
compose-bom = "2024.09.00" // 每月更新
kotlin = "1.9.10"
agp = "8.3.0"
[libraries]
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
compose-ui = { group = "androidx.compose.ui", name = "ui" } // 无版本号
compose-material3 = { group = "androidx.compose.material3", name = "material3" }
// build.gradle.kts (Module级)
dependencies {
implementation(platform(libs.compose.bom)) // 统一版本
implementation(libs.compose.ui)
implementation(libs.compose.material3)
androidTestImplementation(platform(libs.compose.bom)) // 测试也用同一套
}
1.2 Jetifier & Compose Compiler
// build.gradle.kts (Project级)
buildscript {
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlin.get()}")
}
}
// Module级
composeOptions {
kotlinCompilerExtensionVersion = "1.5.3" // 与Kotlin版本严格对应
}
官方映射表:Compose/Kotlin 兼容性
2. 架构:Google 推荐方案(Compose + MVVM + Navigation + Hilt)
2.1 依赖注入(Hilt)
@HiltAndroidApp
class MyApp : Application()
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
NavGraph()
}
}
}
}
2.2 Navigation for Compose
单 Activity + 多 Screen,无需 Fragment。
@Composable
fun NavGraph(
navController: NavHostController = rememberNavController()
) {
NavHost(navController = navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("detail/{itemId}") { backStack ->
val itemId = backStack.arguments?.getString("itemId")!!
DetailScreen(itemId)
}
}
}
2.3 ViewModel + 状态流
@HiltViewModel
class HomeViewModel @Inject constructor(
private val repo: ItemRepository
) : ViewModel() {
val uiState: StateFlow<HomeUiState> = repo.observeItems()
.map { HomeUiState.Success(it) }
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = HomeUiState.Loading
)
}
sealed interface HomeUiState {
data object Loading : HomeUiState
data class Success(val items: List<Item>) : HomeUiState
data class Error(val msg: String) : HomeUiState
}
2.4 在 Compose 中收集状态
@Composable
fun HomeScreen(
viewModel: HomeViewModel = hiltViewModel(),
navController: NavController
) {
val state by viewModel.uiState.collectAsStateWithLifecycle() // 生命周期感知
when (val s = state) {
HomeUiState.Loading -> FullScreenLoading()
is HomeUiState.Success -> ItemList(s.items, navController)
is HomeUiState.Error -> FullScreenError(s.msg)
}
}
collectAsStateWithLifecycle需要依赖
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")
3. 主题与深色模式(Material3 动态配色)
3.1 动态配色(Android 12+)
val dynamic = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
val colorScheme = when {
dynamic && dark -> dynamicDarkColorScheme(LocalContext.current)
dynamic && !dark -> dynamicLightColorScheme(LocalContext.current)
dark -> DarkColorScheme
else -> LightColorScheme
}
3.2 全局字体/形状
MaterialTheme(
colorScheme = colorScheme,
typography = AppTypography, // 自定义 Typography
shapes = AppShapes, // 自定义 Shape
content = content
)
使用 Material Theme Builder 一键导出 Compose 代码。
4. 列表与性能:LazyColumn 深度优化
4.1 使用 key 避免滑动错位
LazyColumn {
items(items = list, key = { it.id }) { item ->
ItemRow(item)
}
}
4.2 大数据分页(Paging3 + Compose)
@Composable
fun PagedListScreen(viewModel: MyViewModel = hiltViewModel()) {
val lazyItems = viewModel.pager.collectAsLazyPagingItems()
LazyColumn {
items(lazyItems.itemCount) { index ->
lazyItems[index]?.let { ItemRow(it) }
}
when (lazyItems.loadState.append) {
is LoadState.Loading -> item { LoadingFooter() }
is LoadState.Error -> item { RetryFooter { lazyItems.retry() } }
else -> Unit
}
}
}
5. 动画(常用模式速查)
| 场景 | API | 示例 |
|---|---|---|
| 可见/消失 | AnimatedVisibility | AnimatedVisibility(visible = expanded) { … } |
| 内容大小 | animateContentSize | Modifier.animateContentSize() |
| 颜色/高宽 | animateColorAsState | val color by animateColorAsState(if (ok) Green else Red) |
| 自定义矢量 | AnimatedNavHost + rememberInfiniteTransition | 官方文档 |
6. 调试与测试
6.1 预览参数化
@Preview(name = "Small", device = "id:pixel_5", fontScale = 0.85)
@Preview(name = "Large", device = "id:pixel_5", fontScale = 1.5)
annotation class FontScalePreviews
@FontScalePreviews
@Composable
fun GreetingPreview() { Greeting("Compose") }
6.2 截图测试(Compose + Paparazzi)
@Test
fun snapHomeLoading() {
paparazzi.snapshot {
MyAppTheme { HomeUi(state = HomeUiState.Loading) }
}
}
Paparazzi 无需真机/模拟器,CI 极快。
6.3 无障碍
semantics语义树自动合并,手动加contentDescription- 使用
Modifier.semantics { heading(); liveRegion() }让 TalkBack 更智能
7. 常见坑 & 解决方案
| 问题 | 原因 | 解决 |
|---|---|---|
| 重组无限循环 | 在 Composable 里 new 对象 | 用 remember { } 或提到 ViewModel |
| 列表滑动卡顿 | 没加 key / 图片没裁剪 | 加 key,用 Coil+crossfade(true)+size |
| 预览报错 “@Composable invocations can only happen from…” | 预览函数里直接调用 ViewModel | 把状态抽离成参数,预览传假数据 |
| 编译慢 | Kotlin/Compose 插件版本对不上 | 严格按 BOM + 官方映射表 锁定版本 |
8. 混淆与打包(上线前必做)
# Compose 专用
-dontwarn androidx.compose.**
-keepattributes SourceFile,LineNumberTable
-keep @androidx.compose.runtime.Composable class * { *; }
# Navigation
-keep class * extends androidx.navigation.Navigator
# Coil
-keep class coil.** { *; }
Compose 本身已内置 R8 规则,只需加第三方库 的补充规则。
9. 持续集成(GitHub Actions 片段)
- name: Unit & Screenshot tests
run: ./gradlew testDebugUnitTest verifyPaparazziDebug
- name: Build & Upload to Play
run: ./gradlew bundleRelease
截图测试失败时,CI 自动生成
build/reports/paparazzi/failure.png,可直接下载对比。

1600

被折叠的 条评论
为什么被折叠?



