Jetpack Compose 性能优化实战
从原理到实践,打造流畅的 Compose 应用
目录
Compose 渲染原理概述
重组(Recomposition)优化
状态管理最佳实践
作用域与 remember 的正确使用
实战案例:列表性能优化
1. Compose 渲染原理概述 Composable 函数的本质 Compose 不是”命令式 UI”的替代,而是声明式 的描述:
1 2 3 4 5 6 @Composable fun MyButton (text: String , onClick: () -> Unit ) { Button(onClick = onClick) { Text(text) } }
每次重组时:
Composable 函数重新执行
描述新的 UI 状态
Compose 比较新旧”描述”(diffing)
只更新实际变化的 UI
重组(Recomposition)触发条件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Composable fun Counter () { var count by remember { mutableIntStateOf(0 ) } Button(onClick = { count++ }) { Text("Count: $count " ) } Button(onClick = { count++ }) { Text("Count: $count " ) } }
真正触发重组的条件 :
State 对象发生 equals 变化
@Composable 参数变化
2. 重组(Recomposition)优化 问题:过度重组 1 2 3 4 5 6 7 8 9 10 11 @Composable fun UserScreen (viewModel: UserViewModel = hiltViewModel() ) { val uiState by viewModel.uiState.collectAsState() Column { Header(uiState.user) Content(uiState.posts) Footer(uiState.timestamp) } }
解决:细化状态粒度 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 data class UserUiState ( val user: User = User(), val posts: List<Post> = emptyList(), val timestamp: Long = 0 ) class UserViewModel : ViewModel () { private val _user = MutableStateFlow(User()) val user: StateFlow<User> = _user.asStateFlow() private val _posts = MutableStateFlow<List<Post>>(emptyList()) val posts: StateFlow<List<Post>> = _posts.asStateFlow() } @Composable fun UserScreen ( user: User , posts: List <Post >, timestamp: Long ) { Column { Header(user) Content(posts) Footer(timestamp) } }
使用 DerivedStateOf 避免不必要的计算 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Composable fun ArticleList (articles: List <Article >) { val sortedArticles = articles.sortedByDescending { it.date } val sortedArticles by remember(articles) { derivedStateOf { articles.sortedByDescending { it.date } } } LazyColumn { items(sortedArticles) { article -> ArticleItem(article) } } }
3. 状态管理最佳实践 避免不必要的 State 提升 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Composable fun BadExample () { var text by remember { mutableStateOf("" ) } var list by remember { mutableStateOf(listOf<String>()) } ChildComponent(text = text, list = list) } @Composable private fun ChildComponent (text: String , list: List <String >) { Text(text) }
正确:状态就近管理 1 2 3 4 5 6 @Composable fun GoodExample () { var text by remember { mutableStateOf("" ) } TextField(value = text, onValueChange = { text = it }) }
ViewModel 状态如何暴露 1 2 3 4 5 6 7 8 class MyViewModel : ViewModel () { private val _uiState = MutableStateFlow(UiState()) val uiState: StateFlow<UiState> = _uiState.asStateFlow() val mutableState = MutableStateFlow(UiState()) }
4. 作用域与 remember 的正确使用 理解 Composable 作用域 1 2 3 4 5 6 7 8 9 10 11 12 @Composable fun Parent () { val data = remember { loadData() } Child() } @Composable private fun Child () { }
正确使用 rememberSaveable 1 2 3 4 5 6 7 8 9 10 11 @Composable fun Screen () { var name by rememberSaveable { mutableStateOf("" ) } var age by rememberSaveable { mutableIntStateOf(0 ) } val cachedData by remember(key1 = userId) { repository.getUserData(userId) } }
mutableStateOf vs mutableIntStateOf 1 2 3 4 5 6 7 8 9 10 11 12 13 @Composable fun PerformanceDemo () { var count by remember { mutableStateOf(0 ) } count++ var count by remember { mutableIntStateOf(0 ) } count++ var value by remember { mutableFloatStateOf(0f ) } }
5. 实战案例:列表性能优化 原始版本:性能问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Composable fun ArticleList (articles: List <Article >) { LazyColumn { items(articles.size) { index -> val article = articles[index] ArticleCard( title = article.title, onClick = { }, modifier = Modifier.fillMaxWidth() ) } } }
优化版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Composable fun ArticleList (articles: List <Article >) { LazyColumn { items( items = articles, key = { it.id } ) { article -> val onClick = remember(article.id) { { } } ArticleCard( title = article.title, onClick = onClick, modifier = Modifier.fillMaxWidth() ) } } }
进阶:懒加载 + 预取 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Composable fun OptimizedList ( viewModel: ListViewModel = hiltViewModel() ) { val items by viewModel.items.collectAsState() LazyColumn( beyondBoundsItemCount = 5 ) { items( items = items, key = { it.id } ) { item -> ListItem( item = item, onClick = { viewModel.onItemClick(item.id) } ) } } }
使用 AsyncImage 优化图片加载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Composable fun ImageOptimized () { AsyncImage( model = ImageRequest.Builder(LocalContext.current) .data (url) .crossfade(true ) .memoryCacheKey(url) .diskCacheKey(url) .build(), contentDescription = null , modifier = Modifier.fillMaxWidth(), contentScale = ContentScale.Crop ) }
性能检查清单
检查项
状态
使用 rememberSaveable 保存 UI 状态
✅
LazyColumn 使用 key 参数
✅
使用 derivedStateOf 避免重复计算
✅
避免在 Composable 中创建 lambda
✅
使用原始类型 mutableIntStateOf
✅
列表使用 AsyncImage 加载图片
✅
StateFlow 暴露给 Compose
✅
避免过度状态提升
✅
总结 Compose 性能优化的核心:
减少重组 :细化状态粒度,使用 derivedStateOf
避免重排 :为列表项提供稳定 key
减少计算 :使用 remember 缓存复杂计算
正确引用 :避免创建不必要的 lambda
相关文章 :