📋 LazyColumn 数据类型 List · MutableList · StateList · SnapshotStateList

⚡ 性能影响实战 选择合适的数据容器,避免重组风暴
类型 可变性 Compose 感知 重组触发 性能场景
List<T> 只读 ❌ 无快照 整体替换 (新实例) ✅ 静态列表
MutableList<T> 可变 ❌ 无快照 整体替换 (引用变化) ⚠️ 不推荐 (需手动通知)
StateList<T>
(mutableStateListOf)
可变 + 快照 ✅ 快照委托 按元素/索引细粒度 ✅ 动态列表 推荐
SnapshotStateList<T>
(mutableStateListOf 内部)
可变 + 快照 ✅ 深度快照 元素级 + 结构性 ✅ 高频更新 首选

📌 选择指南

  • List / MutableList — 仅用于不依赖 Compose 重组的数据源,或一次性加载。每次赋值新列表会触发全部重组。
  • StateList (mutableStateListOf) — 内部使用 SnapshotStateList,支持项目级更新。增删改只重组受影响 item,性能优异。
  • SnapshotStateList — 与 StateList 本质相同,但直接操作快照委托。适合大量 item 局部刷新(如点赞、编辑)。
  • 不要 用 MutableList + 手动 `notify` 方式,易遗漏且破坏声明式。
  • 经验:超过 200 条动态列表,务必使用 `mutableStateListOf`。

🧩 数据流 & 重组范围

List<T> MutableList StateList SnapshotStateList 整体替换 快照感知 深度快照 ⭐ 推荐 StateList / SnapshotStateList
📦 不可变 ⚡ 可变+快照 🎯 元素级重组

💻 实战代码 · 正确使用 SnapshotStateList

// 声明:使用 mutableStateListOf  (SnapshotStateList)
val items = remember { mutableStateListOf(
    "🍎 苹果", "🍊 橙子", "🍋 柠檬", "🍇 葡萄"
) }

// LazyColumn 自动感知元素级变化
LazyColumn {
    itemsIndexed(items) { index, fruit ->
        ListItem(
            title = fruit,
            // 仅修改单个元素,只重组当前 item
            onDelete = { items.removeAt(index) },
            onRename = { items[index] = "🥝 猕猴桃" }
        )
    }
}

// ❌ 错误:使用 MutableList + 重新赋值
// var list = mutableListOf(...)  每次 set 都会重组整个 LazyColumn
🔹 避免 使用 MutableList + 整体赋值
🔹 使用 mutableStateListOf 实现增量更新
🔹 配合 key 参数减少重组范围

核心结论: 对于 LazyColumn 动态列表,始终使用 mutableStateListOf (SnapshotStateList)。 它提供元素级快照,仅重组变化的 item,避免全量重组。List/MutableList 仅适用于静态数据或一次性加载。