Jetpack Compose 核心用法
版本unknown 更新日志2025-11-18 GitHubandroidx/androidx
340px

@Composable 基础 >>>

  • 以 @Composable 声明;仅在组合阶段调用组合 API
  • 布局:Row/Column/Box/Spacer;约束与对齐由 Modifier 控制
  • 预览:@Preview 多参数展示(设备/主题/字体缩放)
  • 示例:
    @Composable
    fun Greeting(name: String) { Text("Hello, $name") }
  • 组合三阶段:ComposeLayoutDraw
  • 无/有状态拆分:UI 无副作用;状态上提(State hoisting)
  • 依赖注入:CompositionLocalCompositionLocalProvider 覆盖提供
  • 上下文:LocalContext.currentLocalDensity.currentLocalLayoutDirection
  • 示例:
    val LocalGreeting = staticCompositionLocalOf { "Hi" }
    @Composable fun Banner() {
      CompositionLocalProvider(LocalGreeting provides "你好") {
        Text(LocalGreeting.current)
      }
    }
  • 保存:rememberSaveable + Saver 自定义序列化保存跨重建

状态与重组 >>>

  • 记忆:var s by remember { mutableStateOf(0) }rememberSaveable 跨重建
  • 派生:val even by remember { derivedStateOf { s % 2 == 0 } }
  • 上提:State hoisting 将状态上移,Composable 保持无副作用
  • 稳定性:优先传递稳定类型;避免捕获不稳定 lambda 触发重组
  • 整型状态:mutableIntStateOf/mutableLongStateOf(减少装箱)
  • 保持最新引用:val current by rememberUpdatedState(value) 避免闭包陈旧
  • 集合:mutableStateListOf/mutableStateMapOfSnapshotStateList
  • 记忆键:remember(key1, key2) { ... } 键变化即重建记忆值
  • 昂贵计算:用 derivedStateOf 缓存并延迟计算(按需)
  • 数据不可变:数据类尽量不可变;必要时 @Immutable/@Stable
  • Flow 转状态:优先 collectAsStateWithLifecycle()(见“Lifecycle”卡)

副作用与生命周期 >>>

  • 启动:LaunchedEffect(key) { /* suspend work */ }
  • 释放:DisposableEffect(key) { onDispose{ /* clean */ } }
  • 快照:snapshotFlow { state } 转 Flow 并收集
  • 作用域:val scope = rememberCoroutineScope() 触发事件
  • 一次性副作用:SideEffect { /* commit to UI tree */ }
  • 将外部源转为状态:produceState(initial) { /* emit via value= */ }
  • 只执行一次:LaunchedEffect(Unit);依赖改变即重启副作用
  • 示例:
    @Composable
    fun UserPanel(vm: VM){
      val user by produceState(null) {
        value = runCatching { vm.load() }.getOrNull()
      }
      user?.let { Text(it.name) }
    }

布局与修饰符 >>>

  • 常用:Modifier.padding/size/fillMaxWidth/weight
  • 排列/对齐:Arrangement.*Alignment.* 组合
  • 自定义:Layout{{ measurables, constraints -> /* measure/place */ }}
  • 测量策略:优先考虑最小/最大约束与基线对齐
  • 约束布局:ConstraintLayout(可选依赖)
  • 复杂场景:SubcomposeLayout 用于先测后绘/延迟子项
  • 尺寸约束:widthIn/heightIn;比例:aspectRatio;层级:zIndex
  • 定位:onGloballyPositioned 获取坐标与尺寸;密度:LocalDensity
  • 绘制:drawBehind/drawWithContent 自定义绘制
  • 裁剪/圆角:clip(RoundedCornerShape(...))border/background
  • 示例:
    Box(Modifier
      .size(88.dp)
      .drawBehind { drawCircle(color = Color(0x2288CCFF)) }
    ){ /* content */ }

列表与懒加载 >>>

  • LazyColumn {
      items(items, key = { it.id }) { item -> ItemRow(item) }
    }
  • 稳定 key:避免错位与无用重组;配合 remember 缓存
  • 分页:Paging3 + collectAsLazyPagingItems()
  • 占位:骨架屏/渐变 shimmer 与 animate* 系列
  • 粘性头:stickyHeader;网格:LazyVerticalGridGridCells
  • 性能:尽量使用 item {}/items {} + key,避免重组抖动
  • 内容类型:contentType 有助回收与复用
  • 索引:itemsIndexed;位置动画:animateItemPlacement()
  • 滚动:val state = rememberLazyListState() + animateScrollToItem
  • Paging 状态:LazyPagingItems.loadState 处理加载/错误/重试

Material3 与主题 >>>

  • 使用 MaterialTheme(colorScheme, typography, shapes)
  • 动态色(Android 12+):dynamicDarkColorScheme()
  • 组件:Button/Card/Scaffold/Snackbar/NavigationBar 等
  • 可访问性:对比度、触控目标尺寸、TalkBack 标签
  • 暗色:isSystemInDarkTheme() 切换;动态色不可用时回退静态方案
  • Scaffold:提供 snackbarHosttopBarbottomBar 等插槽
  • 形状与排版:MaterialTheme.shapes/typography 在组件内复用
  • 按钮参数:ButtonDefaults 自定义颜色与内边距

导航与多模块 >>>

  • NavHost(navController, startDestination = "home") {
      composable("home") { Home() }
      composable("detail/{id}") { backStack -> Detail(backStack["id"]) }
    }
  • 模块化:UI/Domain/Data 分层;公开稳定 UI API
  • ViewModel:hiltViewModel() 或手动提供
  • 保存:rememberSaveable + Saver 保存关键状态
  • 控制器:val navController = rememberNavController()
  • 深链接:navDeepLink;嵌套图与返回栈保存
  • 参数:navArgument + NavType(整型/布尔/枚举/Parcelable)
  • 返回:popUpTo/launchSingleTop/restoreState 组合
  • 多栈:BottomBar 多导航栈(每个 tab 一个 back stack)
  • 第三方:accompanist-navigation-animationAnimatedNavHost(可选)

动画与手势 >>>

  • animate*AsStateupdateTransition 构建状态动画
  • 手势:pointerInputdetectTapGestures;协作嵌套滚动
  • 性能:避免在动画每帧分配对象;尽量使用 remember
  • 可见性:AnimatedVisibility;内容切换:AnimatedContent;淡入淡出:Crossfade
  • 无限动画:rememberInfiniteTransition() 周期性动画
  • 插值器:spring/tween/keyframesrepeatablesnap
  • 拖拽/滑动:draggable/swipeablerememberSplineBasedDecay() 惯性
  • 示例:
    val alpha by animateFloatAsState(if (shown) 1f else 0f)
    Box(Modifier.alpha(alpha))

测试与互操作 >>> Interop

  • UI 测试:composeTestRule.onNodeWithText(...).assertIsDisplayed()
  • 互操作:AndroidView 嵌入 View;ComposeView 嵌入 Compose
  • 性能:使用 Baseline Profiles 优化首帧与滚动
  • 语义:Modifier.semantics { }testTag 作为稳定选择器
  • ComposeView:设置 setViewCompositionStrategy 管理生命周期
  • 规则:createComposeRule()/createAndroidComposeRule<Activity>()
  • 动作:performClick/performTextInput;等待:waitUntil/awaitIdle
  • AndroidView:使用 update 同步状态;避免重复创建 View

Lifecycle 与 Flow 收集 >>>

  • 与生命周期对齐:collectAsStateWithLifecycle()lifecycle-runtime-compose
  • 示例:
    val uiState by viewModel.state.collectAsStateWithLifecycle()
  • 场景:列表分页、搜索防抖、仅在前台收集
  • 等效方案:LaunchedEffect + repeatOnLifecycle 收集
  • ViewModel:在 VM 层 stateIn/shareIn 稳定曝光 UI 状态

文本输入与焦点 >>>

  • 键盘选项:keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search)
  • 键盘动作:keyboardActions = KeyboardActions(onSearch = { ... })
  • 焦点控制:val focus = remember { FocusRequester() } + modifier.focusRequester(focus)
  • 管理器:val fm = LocalFocusManager.currentfm.clearFocus() 隐藏键盘)
  • 输入框:TextField/OutlinedTextFieldsingleLine/maxLines
  • 显示:placeholder/label;变换:VisualTransformation
  • 焦点属性:focusProperties 自定义焦点转移;监听 onFocusChanged
  • 视野:bringIntoViewRequester 与 IME 顶起配合

资源与图片加载 >>>

  • 本地资源:Image(painterResource(R.drawable.cover), contentDescription = null)
  • 网络图片(Coil):AsyncImage(model, contentDescription) 占位/错误图
  • 裁剪模式:contentScale = ContentScale.Crop/Fit/Inside
  • 形状:Modifier.clip(CircleShape) + border 头像样式
  • Coil 构建:
    val req = ImageRequest.Builder(context)
      .data(url).crossfade(true)
      .placeholder(R.drawable.ph).error(R.drawable.err)
      .build()
    AsyncImage(model = req, contentDescription = null)

可访问性与语义 >>>

  • 语义描述:Modifier.semantics { contentDescription = "..." }
  • 角色/合并:role = Role.ButtonmergeDescendants = true
  • 只读覆盖:Modifier.clearAndSetSemantics { };状态:stateDescription
  • 标题:heading() 标记分组标题;禁用项:disabled()
  • 进度:提供范围与值;开关:确保 toggleable 与描述准确
  • 测试:与 onNode(hasTestTag()/hasContentDescription()) 搭配

性能与稳定性 >>>

  • 稳定模型:@Stable/@Immutable;避免可变公开字段
  • 记忆:remember/derivedStateOf;在动画/列表中避免每帧分配
  • Lazy 列表:提供稳定 key;避免捕获不稳定 lambda
  • 更新引用:rememberUpdatedState;差分绘制优先
  • 工具:Layout Inspector、Compose Tracing、Baseline Profiles(Macrobenchmark)
  • 阶段职责:计算放在 Compose;I/O 放在副作用;绘制放在 Draw
  • 避免布局抖动:固定 contentType 与稳定尺寸,减少重测量
  • 图片:开启 crossfade 需评估性能;使用内存缓存策略

预览技巧 >>>

  • 多主题:@PreviewLightDark;动态色:@PreviewDynamicColors
  • 字体缩放:@PreviewFontScale;多设备参数化预览
  • 可交互预览:使用参数构造不同状态场景
  • 系统 UI:@Preview(showSystemUi = true);背景:showBackground
  • 设备:@Preview(device = "id:pixel_6") 等预设
  • 成组:定义多个 @Preview 覆盖光/暗/字体缩放组合

窗口与系统栏 >>>

  • 安全区域:statusBarsPadding()/navigationBarsPadding()/systemBarsPadding()
  • 返回处理:BackHandler(enabled) { /* handle back */ }
  • 系统栏着色:accompanist-systemuicontroller(可选依赖)
  • 输入法:imePadding()/windowInsetsPadding(WindowInsets.ime)
  • 边到边:透明系统栏 + 内边距适配,确保可触达