跳转到正文
YGJoon 技术博客

Android Kotlin Jetpack Compose 实战指南

发布于:
·1.0k 字 · 约 3 分钟·作者:
Compose 从入门到上线:remember 状态、Modifier 链、LaunchedEffect 副作用边界,外加重组性能和 UI 测试的关键点。
Android Kotlin Jetpack Compose 实战指南文章封面
目录

基本组件与函数签名

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(text = "Hello $name!", modifier = modifier.padding(16.dp))
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Greeting("Android")
}

状态管理

remember 与 mutableStateOf

@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) }
    Button(onClick = { count++ }) {
        Text("点击次数:$count")
    }
}

rememberSaveable

var text by rememberSaveable { mutableStateOf("") }

StateFlow + collectAsStateWithLifecycle

@Composable
fun HomeScreen(viewModel: HomeViewModel = hiltViewModel()) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    when (state) {
        is UiState.Loading -> Loading()
        is UiState.Success -> ArticleList(state.data)
        is UiState.Error -> ErrorView(state.error)
    }
}

布局与 Modifier

val listModifier = Modifier
    .fillMaxSize()
    .background(MaterialTheme.colorScheme.background)

LazyColumn(modifier = listModifier) {
    items(articles) { article -> ArticleItem(article) }
}

副作用处理

API用途
LaunchedEffect启动协程执行一次性任务
DisposableEffect注册/注销监听
rememberUpdatedState捕捉最新 lambda,避免闭包问题
SideEffect在每次成功重组后与外部世界同步
@Composable
fun AutoRefresh(onRefresh: () -> Unit) {
    val latestOnRefresh by rememberUpdatedState(onRefresh)
    LaunchedEffect(Unit) {
        while (true) {
            delay(5_000)
            latestOnRefresh()
        }
    }
}

动画

val alpha by animateFloatAsState(
    targetValue = if (visible) 1f else 0f,
    animationSpec = tween(durationMillis = 300)
)

AnimatedVisibility(visible = expanded) {
    Text("详情内容")
}

Compose + Navigation

@Composable
fun AppNavGraph(navController: NavHostController = rememberNavController()) {
    NavHost(navController, startDestination = "home") {
        composable("home") { HomeScreen(onNavigate = { navController.navigate("detail/$it") }) }
        composable(
            route = "detail/{id}",
            arguments = listOf(navArgument("id") { type = NavType.LongType })
        ) { backStackEntry ->
            val id = backStackEntry.arguments?.getLong("id") ?: return@composable
            DetailScreen(id)
        }
    }
}

性能优化

LazyColumn {
    items(items = messages, key = { it.id }) { message ->
        MessageItem(message)
    }
}

测试策略

@RunWith(AndroidJUnit4::class)
class HomeScreenTest {
    @get:Rule
    val composeRule = createAndroidComposeRule<MainActivity>()

    @Test
    fun showLoading() {
        composeRule.onNodeWithText("加载中").assertExists()
    }
}

常见问题

问题原因解决方案
重组频繁状态对象不稳定使用 remember、derivedStateOf
滚动跳动LazyList item 未提供稳定 key在 items 中提供唯一 key
状态丢失使用 remember 而非 rememberSaveable对需持久状态使用 rememberSaveable

实战案例:Compose 和 Flutter 的声明式 UI 是亲兄弟

Compose 的心智模型和 Flutter 几乎一模一样:@Composable ≈ StatelessWidget/StatefulWidget,remember ≈ State,State<T> ≈ ValueNotifier,LazyColumn ≈ ListView.builder。我第一次看 Compose 代码时,最大的感觉是”这我熟”。

但有两处关键差异,Flutter 开发者转 Compose 必须注意:

  1. 重组(recomposition)比 Flutter 的 rebuild 更激进。Flutter 的 setState 只 rebuild 当前 subtree,Compose 的重组范围由编译器插件决定,写不好会大面积重组。官方为此给了 derivedStateOf(≈ Flutter 的 ValueListenableBuilder 做细粒度)和 @Stable/@Immutable 注解——Flutter 里没有对等物,因为 Dart 没有编译器插件这层。
  2. 副作用 API 更显式。LaunchedEffect ≈ initState 里开协程,DisposableEffect ≈ dispose,SideEffect ≈ addPostFrameCallback。Compose 把”什么时候执行”写进 API 名字,Flutter 靠生命周期方法隐式约定。初学觉得啰嗦,项目大了才知道这是救命设计。

一句话:会 Flutter 的人学 Compose,最快路径是”找对应物”,而不是从零学。两套框架在互相抄作业。

参考:Android 官方文档《Jetpack Compose》思维模型章节;《Compose mental model》

总结

  1. Jetpack Compose 通过函数式 UI 与 Kotlin 状态管理提升开发效率。
  2. 熟练掌握 remember、Flow、SideEffect 等 API,可构建响应式界面。
  3. 关注性能与测试,才能在大型项目中稳定落地 Compose。

下一篇将探讨 Kotlin 在架构组件与多模块协同中的实践。


分享这篇文章:


相关文章

上一篇
Android Kotlin DataStore 配置与迁移
下一篇
Android Kotlin Room 数据库进阶实践