跳转至

第07章 状态管理与性能优化

状态管理与性能优化图

学习目标:掌握高级状态管理技巧和性能优化方法。

预计学习时间:5-7天 实践时间:2-3天


目录

  1. 高级状态管理
  2. 重组优化
  3. 性能优化技巧
  4. 内存管理
  5. 实践练习

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分析内存 - 修复内存泄漏 - 优化图片加载 - 减少内存抖动


本章小结

核心要点

  1. 状态管理应分层设计,避免过度集中
  2. 重组优化通过稳定性、key和延迟加载实现
  3. 动画性能使用Compose提供的动画API
  4. 内存管理注意生命周期和引用关系

下一步

完成本章学习后,请进入第08章:AI辅助开发集成指南


本章完成时间:预计5-7天