1. 理解Jetpack Compose中的副作用机制
在Jetpack Compose的世界里,副作用(Side Effect)是个绕不开的话题。我第一次接触这个概念时也是一头雾水,直到踩了几个坑才真正明白它的重要性。简单来说,副作用就是那些在Composable函数执行过程中,对外部状态产生的"额外影响"。
举个例子,假设你在Composable函数里直接修改了一个全局变量,或者调用了某个网络请求,这些操作都算是副作用。为什么这会有问题呢?因为Compose的UI是通过重组机制来更新的,而重组可能会在任何时候、以任何顺序发生多次。
我刚开始用Compose时犯过一个典型错误:在一个Composable函数里直接修改了Activity的标题。看起来代码运行正常,直到有一天用户快速切换页面时,发现标题莫名其妙地乱跳。这就是典型的副作用问题——重组发生时,这个修改操作被重复执行了。
2. LaunchedEffect的实战应用
2.1 一次性初始化操作
LaunchedEffect是我用得最多的副作用处理API。它的核心作用有两个:确保代码只执行一次,以及提供协程作用域。先说说第一个用法:
@Composable
fun UserProfileScreen(userId: String) {
LaunchedEffect(Unit) {
viewModel.loadUserProfile(userId)
}
// 其他UI代码...
}
这段代码中的loadUserProfile只会执行一次,即使UserProfileScreen因为其他原因发生重组也不会重复调用。Unit作为key值,表示"我只关心第一次执行"。
2.2 响应式执行与协程管理
LaunchedEffect更强大的地方在于它可以响应参数变化。比如当userId变化时,我们想重新加载用户数据:
@Composable
fun UserProfileScreen(userId: String) {
LaunchedEffect(userId) {
viewModel.loadUserProfile(userId)
}
// 其他UI代码...
}
这里的关键点是:当userId变化时,之前的协程会被自动取消,新的协程会启动。这个特性在处理分页加载时特别有用,可以避免快速滑动列表时产生的大量并发请求。
我在实际项目中发现一个常见误区:很多人会忘记处理协程取消的情况。比如:
LaunchedEffect(userId) {
try {
val data = repository.fetchData(userId)
// 处理数据
} catch (e: CancellationException) {
// 必须处理取消异常
}
}

1043

被折叠的 条评论
为什么被折叠?



