Jetpack Compose 入门指南


✅ 一、Jetpack Compose 是什么?

Jetpack Compose 是 Google 推出的现代声明式 UI 工具包,用于构建 Android 原生界面。它使用 Kotlin 语言,无需 XML 布局文件,通过函数调用的方式描述界面。


🧰 二、开发环境准备

  1. 安装 Android Studio(建议使用最新版)
  2. 创建新项目时选择 “Empty Compose Activity”
  3. 最低支持 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 使用 remembermutableStateOf 来管理局部状态:

@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 组件库,常用组件包括:

  • Button
  • TextField
  • Card
  • Scaffold(页面骨架)

七、基本配置

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示例
可见/消失AnimatedVisibilityAnimatedVisibility(visible = expanded) { … }
内容大小animateContentSizeModifier.animateContentSize()
颜色/高宽animateColorAsStateval 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,可直接下载对比。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bryce李小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值