Android Compose 中,@Immutable 和 @Stable 的理解

Jetpack Compose 中的稳定性(Stability)

Compose 编译器通过分析对象的稳定性来决定是否跳过重组(Recomposition)。如果一个对象被认为是"稳定"的,那么当它作为参数传入到 Composable 函数中时,只要引用没有变化,Compose 就可以跳过对该函数的重组。 参考 developer.android.com/develop/ui/... developer.android.com/develop/ui/...

1.@Immutable

表示这个类是完全不可变的(immutable),所有属性都是 val 且不会改变。

Compose 编译器会认为这样的对象在整个生命周期内都不会发生变化。

特点: 所有字段必须是 val。 推荐用于数据模型类(如:用户信息、配置等)。 适用于纯数据类,比如 Kotlin 的 data class。 可以安全地跳过重组,提高性能。

kotlin 复制代码
@Immutable 
data class User(val id: Int, val name: String)
如果你试图用 var 字段,编译器会警告你该类可能不稳定。

2.@Stable

表示这个类是"稳定的",但允许包含可变字段(如 var),前提是这些字段的变化不会影响 UI 的状态,或者你已经通过 Compose 的响应式机制(如 mutableStateOf)管理了其变化。

特点: 允许使用 var。 需要开发者自己保证类的行为符合"稳定性"要求。 如果某个字段确实会变化但你不希望触发重组,可以用 @Stable 告诉 Compose 忽略它。 如果你想让某些字段变化也能触发重组,可以在这些字段中使用 mutableStateOf()。

kotlin 复制代码
@Stable 
class Counter { 
    var name:String ="abc"
    var count by mutableStateOf(0)
    private fun increment() { count++ }
}
`count` 是 `var`,但它是一个 `mutableStateOf`,
Compose 能追踪它的变化并触发重组。
整个 `Counter` 类被标记为 `@Stable`,
Compose 认为它是稳定的,不会因为 name 改变而进行重组,因为 Compose 不会追踪它的变化,
除非 `count` 改变,否则不会重组。
html 复制代码
使用 @Stable 的注意事项
如果你滥用 @Stable,可能会导致:
状态更新不触发重组 → 页面无法刷新。
性能优化过度 → UI 不同步于数据。
所以建议:
如果类是纯粹的数据结构,优先使用 @Immutable。
如果类封装了一些逻辑或状态管理,再考虑使用 @Stable。
永远不要对会频繁变化的类使用 @Stable,除非你知道自己在做什么。

ompose 如何判断稳定性?
Compose 编译器会根据以下规则判断一个类是否稳定:

判断条件	                                  是否稳定
所有属性是 val,且类型稳定	                 ✅ 是(默认 @Immutable)
使用了 @Stable 注解	                         ✅ 视为稳定
包含 mutableStateOf 或其他可观察类型       	 ✅ 可追踪变化
属性是 var,未使用任何注解	                 ❌ 不稳定

总结

在 Android Compose 中,@Immutable 和 @Stable 都是用来声明稳定性的,告诉编译器,如果你定义了普通的 class类对象,里面的字段不是 val 的那么,compose 会统一认为是不稳定的,就会进行重组,Compsoe提供了@Immutable注解,这个注解的类必须是 val 不可变的,就很稳定了。@Stable 声明的类是告诉 Compose 我很稳定,即使我有var 字段的变量,我也很稳定,可以跳过重组,但是这样话,如果值发生变化,compose 就追踪不了,无法重组,页面就无法发生变化,这是不对的,当然你可以在@Stable定义的类中,定义 compose 可追踪的状态,例如muatbleStateOf()。当发生变化,就会重组,进行页面变化了。

相关推荐
F2E_Zhangmo2 小时前
基于cornerstone3D的dicom影像浏览器 第三章 拖拽seriesItem至displayer上显示第一张dicom
前端·javascript·cornerstone·cornerstone3d·cornerstonejs
gnip7 小时前
Jst执行上下文栈和变量对象
前端·javascript
excel7 小时前
🐣 最简单的卷积与激活函数指南(带示例)
前端
醉方休8 小时前
npm/pnpm软链接的优点和使用场景
前端·npm·node.js
拉不动的猪8 小时前
简单回顾下Weakmap在vue中为何不能去作为循环数据源,以及替代方案
前端·javascript·vue.js
How_doyou_do8 小时前
数据传输优化-异步不阻塞处理增强首屏体验
开发语言·前端·javascript
奇舞精选8 小时前
超越Siri的耳朵:ASR与Whisper零代码部署实战指南
前端·人工智能·aigc
奇舞精选8 小时前
Nano Banana 如何为前端注入 AI 控制力
前端·aigc
一支鱼8 小时前
基于 Node.js 的短视频制作神器 ——FFCreator
前端·node.js·音视频开发
DT——8 小时前
前端登录鉴权详解
前端·javascript