是否应该将Compose中的状态切分

如题,为什么会有这种疑问呢?

我们知道Compose是通过重组来刷新UI的,当一个State发生改变时,其对应的可重组函数的Lambda会重新执行,而我们通常在设计State时都是将当前界面相关属 combine成一个整体的State,所以我们在修改State时,其实就是让整个State都发生了变化,基本会让整个界面都发生重组不会跳过。下面通过一个简单的例子:

Kotlin 复制代码
// 一个整合的State
data class XModelState(
    val name: String,
    val age: Int,
    val intro: String
    ...
)
Kotlin 复制代码
Column(
    modifier = Modifier
    .fillMaxSize()
    .padding(16.dp)
) {
    
    println("Column")

    Wrapper {
        Text(text = "Name is ${modelState.name}").also {
            println("Name changed")
        }
    }
    Wrapper {
        Text(text = "Age is ${modelState.age}").also {
            println("Age changed")
        }
    }
    Wrapper {
        Text(text = "Intro is ${modelState.intro}").also {
            println("Intro changed")
        }
    }

    Button(
        modifier = Modifier.fillMaxWidth(),
        onClick = {
            modelState = modelState.copy(
                name = "Dougie ${Random.nextInt(0, 10)}",
                age = age + 1
            )
        }
    ) {
        Text(text = "Update Model")
    }
}

以上代码中,当点击Update Model按钮来修改modelState时,3个Wrapper全部都发生重组,假设这个State其实还可能更大,有20多个属性,而当我们只修改 一部分相关的,很多相关的Composable应该skip re-compose。

Kotlin 复制代码
*       ----------------     -----------------      ---------------------
*       | Click Button |  -> | State changed |  ->  | trigger recompose |
*       ----------------     -----------------      ---------------------

为了避免这个情况,目前Compose也没提供相关的api,好像也只能通过分割状态了,对应文章的标题。

1. ViewModel层保留多个公开的State

在ViewModel combine的时候就将State分割并提供多个State叫个UI层使用,而在操作的时候,我们也只会改变其对应的小State,其他State不会变化, 所以Compose上也只会重组其对应的可重组Lambda,而其他的则会跳过重组。

2. 使用 derivedStateOf

在View层,依然是拿到整个大的State,我们通过增加内部属性并使derivedStateOf这个方法将State分割。

Kotlin 复制代码
val age by remember {
    derivedStateOf {
        modelState.age
    }
}
val intro by remember {
    derivedStateOf {
        modelState.intro
    }
}

如上,将age和intro分割出来,在点击按钮是,age+1,而intro不变,通过日志,发现只有Age Changed,所以intro的被跳过重组了。

在日常开发中,需求feature会越来越多,State也会随之而增加,以上两种方式虽然一定程度上能减少重组,但是也很大程度上增加了维护工作 和带来新的问题。

总结

在Compose上,UI的更新必然脱离不了重组,所以重组本身并不是大问题,我们需要注意的是尽量在可重组项中尽量少操作多余的工作。所以通常我们不必在意这些, 因为Compose帮我做了很多优化的工作了。 当然如果在某个UI上,有其中一部份UI变化相对比较频繁,而其他则很少,此时我建议分割出来

原文

相关推荐
松仔log6 小时前
Java中级——组合和继承
android·java·开发语言
我命由我123459 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian23310 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_9557596210 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马10 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone10 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone10 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常
极客猴子14 小时前
Android录音转写频繁卡顿?多款APP长时间会议场景稳定性实测
android·人工智能·智能手机·飞书
Kapaseker14 小时前
Boolean 变量到底该怎么命名?
android·kotlin
AFinalStone14 小时前
Android 7系统异常问题排查(六)应用异常(上)—ANR机制全解
android·系统异常