聊聊JetpackCompose的“状态订阅自动刷新”--mutableStateListOf
- 人工智能
- 2025-07-21 19:20:43

Jekpack Compose “状态订阅&自动刷新” 系列:
【 聊聊 Jetpack Compose 的 “状态订阅&自动刷新” - - MutableState/mutableStateOf 】
【 聊聊 Jetpack Compose 的 “状态订阅&自动刷新” - - remember 和重组作用域 】
【 聊聊 Jetpack Compose 的 “状态订阅&自动刷新” - - 有状态、无状态、状态提升?】
【 聊聊 Jetpack Compose 的 “状态订阅&自动刷新” - - mutableStateListOf 】
【 聊聊 Jetpack Compose 的 “状态订阅&自动刷新” - - 你真的了解重组吗?】
讲任何一个新的主题或者知识点,习惯性的从 Demo 开始,比如:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var name by mutableStateOf("Hi, Compose") setContent { Text(name) } } }这段代码已经熟的不能再熟了,如果我们用 by mutableStateOf 初始化一个变量,那 name 就会变成一个被 Compose 自动订阅的变量。
我们前面所有的例子,都是用 by mutableStateOf 包了一个 String,如果换成别的类型,行不行?肯定可以,不用想。
fun <T> mutableStateOf( value: T, // 泛型参数 policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy() ): MutableState<T> = createSnapshotMutableState(value, policy)比如 Int 类型:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var num by mutableStateOf(1) setContent { Text( text = "当前数值:$num", Modifier.clickable { num++ } ) } } }代码不做解释了,直接看效果:
比如:List 类型
// num 类型:MutableList<Int> // mutableStateOf 类型:MutableState<MutableList<Int>> var nums by mutableStateOf(mutableListOf(1, 2, 3))我们在代码里面用起来:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var nums by mutableStateOf(mutableListOf(1, 2, 3)) setContent { Column { for (num in nums) { Text("第 $num 块文字") } } } } }运行:
现在我们稍微改下代码:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var nums by mutableStateOf(mutableListOf(1, 2, 3)) setContent { Column { Button(onClick = { nums.add(nums.last() + 1) }) { Text("List 加 1") } for (num in nums) { Text("第 $num 块文字") } } } } }代码很简单:我们添加了一个 Button,每次点击后,nums 会添加一个值,比最有一个值大 1。
运行:
???没生效啊!为什么?
我们先来考虑一个问题,mutableStateOf 原理是什么?前面的问题我们说过,可以回忆一下:
mutableStateOf 之所以可以对变量进行订阅和刷新,主要是因为内部的 get() 和 set() 方法加了钩子,或者说它的 set() 方法是赋值!是改变了变量的指向,它是直接把对象可替换了,但在我们这个代码里面 nums 仅仅是改变了它内部的状态:
对这块如果有点懵,可以看【 聊聊 Jetpack Compose 的 “状态订阅&自动刷新” - - MutableState/mutableStateOf 】 这篇文章。
所以,它不会出发 setValue() 的调用,所以不会出发自动刷新的操作。
为了验证是不是因为没有重组,我们可以验证下:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var nums by mutableStateOf(mutableListOf(1, 2, 3)) var refresh by mutableStateOf("强制刷新") setContent { Column { Text(refresh, Modifier.clickable { refresh = "刷新完成"}) Button(onClick = { nums.add(nums.last() + 1) }) { Text("List 加 1") } for (num in nums) { Text("第 $num 块文字") } } } } }我们添加了一个 Text() 组件,改变 refresh 的值,那么理论上它就会带着整个重组作用域内的组件全部刷新,包括 List。
运行:
成功刷新 List!
现在我们就很清楚了,mutableStateOf 没法对 List 类型的对象没法实现类似 String、Int 的自动订阅及刷新,那有没有解决办法?
上面我们说过了,问题的根本原因是 List 只是内部的变化,而不是它自己本身对象的变化,那我们直接在内部操作完后直接把 List 重新给换了不就行了,试试:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var nums by mutableStateOf(mutableListOf(1, 2, 3)) setContent { Column { Button(onClick = { // nums 重新赋值 nums = nums.toMutableList().apply { add(nums.last() + 1) } }) { Text("List 加 1") } for (num in nums) { Text("第 $num 块文字") } } } } }运行:
但这样写就会显得很奇怪,我是明白原理了,我这样也是可以实现正常的刷新,但不太对劲:既然对于 String、Int 这些类型,Compose 提供了 mutableStateOf,难道对于 List 这种这么常用的类型,就没有一个 mutable*** 的函数给我们用?
有,它就是 mutableStateListOf!它可以观测到内部 List 的数据变化!
我们可以像下面这样申明:
var nums by mutableStateListOf(mutableListOf(1, 2, 3)) // 有红线标注,写法错误 // mutableStateListOf 是内部元素被观测,而不是它本身被观测,所以我们要把 `by` 换成 `=` var nums = mutableStateListOf(mutableListOf(1, 2, 3)) // `var` 也可以换成 `val` val nums = mutableStateListOf(mutableListOf(1, 2, 3)) // mutableStateListOf 本身就代表一个可观测的 List,所以 mutableListOf 也可以去除 val nums = mutableStateListOf(1, 2, 3) // 这就是最终的写法这个时候我们就可以优化下代码了:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val nums = mutableStateListOf(1, 2, 3) setContent { Column { Button(onClick = { nums.add(nums.last() + 1) }) { Text("List 加 1") } for (num in nums) { Text("第 $num 块文字") } } } } }运行:
提到 List,我们就会想到 Map,同样 Map 也提供了一个 mutableStateMapOf!它也可以观测到内部 Map 的数据变化!
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val maps = mutableStateMapOf(1 to "One", 2 to "Two") setContent { Column { Button(onClick = { maps[3] = "Three" }) { Text("Maps 加 1") } for ((key, value) in maps) { Text("$key 对应 value: $value") } } } } }运行:
聊聊JetpackCompose的“状态订阅自动刷新”--mutableStateListOf由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“聊聊JetpackCompose的“状态订阅自动刷新”--mutableStateListOf”