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()。当发生变化,就会重组,进行页面变化了。

相关推荐
小飞侠在吗9 小时前
vue props
前端·javascript·vue.js
DsirNg11 小时前
页面栈溢出问题修复总结
前端·微信小程序
小徐_233311 小时前
uni-app 也能远程调试?使用 PageSpy 打开调试的新大门!
前端·微信小程序·uni-app
大怪v11 小时前
【Virtual World 03】上帝之手
前端·javascript
别叫我->学废了->lol在线等13 小时前
演示 hasattr 和 ** 解包操作符
开发语言·前端·python
霍夫曼13 小时前
UTC时间与本地时间转换问题
java·linux·服务器·前端·javascript
DARLING Zero two♡13 小时前
浏览器里跑 AI 语音转写?Whisper Web + cpolar让本地服务跑遍全网
前端·人工智能·whisper
Lovely Ruby13 小时前
前端er Go-Frame 的学习笔记:实现 to-do 功能(三),用 docker 封装成镜像,并且同时启动前后端数据库服务
前端·学习·golang
深红13 小时前
玩转小程序AR-实战篇
前端·微信小程序·webvr
银空飞羽13 小时前
让Trae SOLO全自主学习开发近期爆出的React RCE漏洞靶场并自主利用验证(CVE-2025-55182)
前端·人工智能·安全