移动/游戏
Jetpack Compose…
当 Compose UI 出现渲染慢、滚动卡顿、过度重组等性能问题时,通过代码审查、性能剖析与针对性重构来定位并修复。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
Jetpack Compose 渲染卡顿特定
解决思路
- 若用户提供了代码,直接进入 Code-First Review;若只描述症状,先索取最小代码/上下文再做 Code-First Review;若代码审查无法定论,则引导用户进行性能剖析并索取 Layout Inspector 输出或 Perfetto trace。
- Code-First Review 阶段收集:目标 Composable 代码、数据流(state、remember、derived state、ViewModel 连接)、症状与复现步骤。
- Code-First Review 重点排查:不稳定参数或大范围状态变更导致的重组风暴;LazyColumn/LazyRow 中不稳定 key(key 抖动、缺失 key);组合期内的重活(格式化、排序、过滤、对象分配);不必要的重组(缺少 remember、不稳定类、lambda);未做尺寸约束或异步加载的大图;布局抖动(深层嵌套、intrinsic 测量、SubcomposeLayout 误用)。
- Code-First Review 输出:带代码引用的可能根因、建议的修复与重构、必要时提供最小复现或插桩建议。
- 引导用户剖析:使用 Android Studio 的 Layout Inspector 查看重组次数;在 Compose 工具中启用 Recomposition Highlights;使用 Perfetto 或 System Trace 做帧时序分析;查看 Macrobenchmark 的启动/滚动指标。
- 向用户索取:显示重组次数的 Layout Inspector 截图、Perfetto trace 或 System Trace 导出、设备/OS/构建配置(debug 还是 release)。
- 强调:性能剖析必须在启用 R8 的 release 构建上进行,debug 构建有显著开销。
- 分析诊断时优先排查 Compose 常见元凶:不稳定参数或大范围状态变更导致的重组风暴;lazy 列表中不稳定 key(key 抖动、基于索引的 key);组合期内的重活(格式化、排序、对象分配);缺少 remember 导致每次重组都重建;未用 Modifier.size() 约束的大图;在错误的组合阶段进行不必要的状态读取。
- 结合 trace/Layout Inspector 的证据总结发现。
- 修复措施:用 @Stable 或 @Immutable 注解稳定参数;为 LazyColumn/LazyRow item 使用稳定唯一 ID 稳定 key;用 derivedStateOf、基于 lambda 的 modifier 或 Modifier.drawBehind 延迟状态读取;用 remember { } 或 remember(key) { } 缓存昂贵计算;抽取稳定 composable、用 key() 控制身份以跳过重组;用 Coil/Glide 并配合尺寸约束做异步图片加载;扁平化层级、避免深层嵌套以降低布局复杂度。
- 修复不稳定 lambda 捕获:不要每次重组都新建 lambda(如 Button(onClick = { viewModel.doSomething(item) })),改用 remember 或方法引用(val onClick = remember(item) { { viewModel.doSomething(item) } })。
- 修复组合期内的昂贵操作:不要在每次重组时排序(val sorted = items.sortedBy { it.name }),改用 remember 带 key(val sorted = remember(items) { items.sortedBy { it.name } })。
- 修复 LazyColumn 缺失 key:不要用基于索引的身份(items(items) { item -> ItemRow(item) }),改用稳定 key(items(items, key = { it.id }) { item -> ItemRow(item) })。
- 修复不稳定 data class:含 List 等不稳定字段的 data class 应标注 @Immutable 并使用 kotlinx.collections.immutable 的 ImmutableList。
- 修复过早读取状态:不要在组合期读取状态(val offset = scrollState.value),改用 Modifier.offset { IntOffset(0, scrollState.value) } 将读取延迟到布局阶段。
- 修复组合期对象分配:对动态 modifier 用 remember 缓存(val modifier = remember { Modifier.padding(16.dp).background(Color.Red) })。
- 稳定性检查表:基本类型(Int、String、Boolean)默认稳定;字段都稳定的 data class 默认稳定;List、Map、Set 默认不稳定,改用 kotlinx 的 ImmutableList;含 var 属性的类默认不稳定,若外部稳定可用 @Stable;lambda 默认不稳定,用 remember { }。
- 验证阶段请用户:重新运行 Layout Inspector 对比重组次数;运行 Macrobenchmark 对比帧时序;在真机上用 release 构建测试;若提供数据则总结差值(重组次数、掉帧、卡顿)。
- 输出:简短指标表(有前后对比则附上)、按影响排序的 top 问题、带预估工作量的修复方案。
适用边界 · 注意事项
- 不适用于非 Jetpack Compose 的 UI 框架(如传统 View 体系、Flutter、SwiftUI)。
- 若无法在 release 构建上做性能剖析,诊断结论可能失真,应避免仅凭 debug 构建下结论。
- 若用户既无代码也无任何剖析数据,无法进行有效审查,应先索取最小代码或 trace 再继续。