是否应该将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变化相对比较频繁,而其他则很少,此时我建议分割出来

原文

相关推荐
五彩小白12 小时前
自回归和上下文
android
事圆则缓15 小时前
Android 多渠道打包实战:Product Flavors、签名、AAB 与发包校验
android
树下困觉眯17 小时前
View绘制流程学习--获取WindowManager的三种方式
android·系统架构·view design
vilya18 小时前
我怎么给手机 GUI Agent 做双通道感知:无障碍树为主,投屏像素兜底
android·人工智能
李子红了时19 小时前
阿狸舞台APP(安卓端手机EncFS解密+压缩包解压+视频播放)
android·音视频
事圆则缓19 小时前
Android 使用 Jenkins 实现 CI/CD,并用 SonarQube 建立质量门禁
android·ci/cd·jenkins
其实防守也摸鱼19 小时前
DeepSeek Harness 开源贡献手记:从 Issue 到 Merge 的完整旅程
android·数据库·学习·ai·oracle·自动化
恋猫de小郭19 小时前
Android CLI 支持 AI Agent 通过 Device Streaming 调试云真机
android·前端·flutter
素师良码2 天前
第5篇:显示驱动必备调试工具浅析
android
维克兜率天2 天前
【维克】配对交易的季节性:哪些品种适合长拿?
android·开发语言·笔记·python·算法·kotlin·量化