第07章 状态管理与性能优化¶
学习目标:掌握高级状态管理技巧和性能优化方法。
预计学习时间:5-7天 实践时间:2-3天
目录¶
1. 高级状态管理¶
1.1 状态持有者模式¶
Kotlin
// 屏幕级状态持有者
class NewsListStateHolder(
private val getNewsUseCase: GetNewsUseCase,
private val coroutineScope: CoroutineScope
) {
private val _uiState = MutableStateFlow(NewsUiState())
val uiState: StateFlow<NewsUiState> = _uiState.asStateFlow()
fun loadNews() {
_uiState.update { it.copy(isLoading = true) }
coroutineScope.launch {
getNewsUseCase()
.onSuccess { news ->
_uiState.update {
it.copy(news = news, isLoading = false)
}
}
}
}
}
// 在ViewModel中使用
class NewsViewModel @Inject constructor(
getNewsUseCase: GetNewsUseCase
) : ViewModel() {
private val stateHolder = NewsListStateHolder(getNewsUseCase, viewModelScope)
val uiState = stateHolder.uiState
fun loadNews() = stateHolder.loadNews()
}
1.2 多层级状态管理¶
Kotlin
// 应用级状态
class AppState {
val theme = mutableStateOf(Theme.LIGHT)
val user = mutableStateOf<User?>(null)
}
// 屏幕级状态
class ScreenState {
val isLoading = mutableStateOf(false)
val data = mutableStateOf<List<Item>>(emptyList())
}
// 组件级状态
class ComponentState {
var isExpanded by mutableStateOf(false)
}
2. 重组优化¶
2.1 避免不必要重组¶
Kotlin
// ❌ 问题:整个列表都会重组
@Composable
fun BadList(items: List<Item>) {
Column {
items.forEach { item ->
ItemRow(item) // 任何item变化都会导致全部重组
}
}
}
// ✅ 解决:使用LazyColumn和key
@Composable
fun GoodList(items: List<Item>) {
LazyColumn {
items(
items = items,
key = { it.id } // 使用稳定key
) { item ->
ItemRow(item)
}
}
}
// ✅ 使用remember避免重复计算
@Composable
fun ExpensiveCalculation(data: List<Int>) {
val sum = remember(data) {
data.sum() // 只在data变化时计算
}
Text("Sum: $sum")
}
2.2 稳定性与不可变性¶
Kotlin
// ✅ 使用不可变数据类
data class User(
val id: String,
val name: String
)
// ❌ 避免可变类
class MutableUser {
var id: String = ""
var name: String = ""
}
// ✅ 使用@Stable标记
@Stable
interface UserRepository { // interface定义类型契约
fun getUser(): User
}
// ✅ 使用Immutable集合
@Composable
fun ListScreen(items: ImmutableList<Item>) {
// items变化时才会重组
}
3. 性能优化技巧¶
3.1 延迟加载¶
Kotlin
// LazyColumn自动实现延迟加载
LazyColumn {
items(1000) { index ->
ListItem(index) // 只渲染可见项
}
}
// 图片延迟加载
AsyncImage(
model = ImageRequest.Builder(context)
.data(imageUrl)
.placeholderMemoryCacheKey(previewImageUrl)
.build(),
contentDescription = null
)
3.2 动画性能¶
Kotlin
// 使用animate*AsState而不是手动动画
val animatedProgress by animateFloatAsState(
targetValue = progress,
animationSpec = tween(300),
label = "progress"
)
// 避免在动画中读取状态
Canvas(modifier = Modifier.fillMaxSize()) {
// ❌ 错误:每次重组都会读取
drawCircle(color = if (isSelected) Color.Red else Color.Blue)
// ✅ 正确:使用动画状态
drawCircle(color = animatedColor)
}
4. 内存管理¶
4.1 避免内存泄漏¶
Kotlin
// ❌ 错误:在ViewModel中持有Context引用
class BadViewModel(private val context: Context) : ViewModel()
// ✅ 正确:使用Application Context
class GoodViewModel @Inject constructor(
@ApplicationContext private val context: Context
) : ViewModel()
// ❌ 错误:在Composable中使用非生命周期感知的协程
@Composable
fun BadExample() {
scope.launch { // 可能导致泄漏
// 长时间运行的任务
}
}
// ✅ 正确:使用rememberCoroutineScope
@Composable
fun GoodExample() {
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
// 任务
}
}) {
Text("Click")
}
}
4.2 图片内存优化¶
Kotlin
// 限制图片大小
AsyncImage(
model = ImageRequest.Builder(context)
.data(url)
.size(Size.ORIGINAL)
.scale(Scale.FILL)
.build(),
contentDescription = null,
contentScale = ContentScale.Crop
)
// 使用合适的大小
val size = if (isThumbnail) 100 else 500
AsyncImage(
model = "$url?w=$size",
contentDescription = null
)
5. 实践练习¶
练习1:性能分析¶
任务:分析一个存在性能问题的应用
要求: - 使用Layout Inspector识别问题 - 修复不必要的重组 - 优化列表性能 - 验证改进效果
练习2:内存优化¶
任务:优化应用的内存使用
要求: - 使用Profiler分析内存 - 修复内存泄漏 - 优化图片加载 - 减少内存抖动
本章小结¶
核心要点¶
- 状态管理应分层设计,避免过度集中
- 重组优化通过稳定性、key和延迟加载实现
- 动画性能使用Compose提供的动画API
- 内存管理注意生命周期和引用关系
下一步¶
完成本章学习后,请进入第08章:AI辅助开发集成指南。
本章完成时间:预计5-7天