📚 LazyColumn 核心原理

⚡ 回收 · 复用 · 懒加载

🔁 RecyclerView 对比 LazyColumn

📱 RecyclerView (Android View)

  • Adapter + ViewHolder 模式,手动实现
  • onCreateViewHolder / onBindViewHolder 回调
  • 基于 View 层级,测量/布局开销大
  • 回收池 RecycledViewPool 按 viewType 复用
  • 需要 LayoutManager 控制布局方向
  • DiffUtil 异步计算差异

🚀 LazyColumn (Compose)

  • LazyListScope 声明式 item { }
  • Composable 函数自动 重组 而非绑定
  • 基于 LayoutNode 轻量级,跳过测量
  • 内部 SlotTable 维护位置 & 状态
  • 自动 LazyLayout 预取 + 懒加载
  • Snapshot 系统 + key 稳定复用
对比维度RecyclerViewLazyColumn
复用单位ViewHolder (View)Composable (Slot)
回收机制RecycledViewPool + scrapCompose SlotTable 重组
布局方式onLayoutChildren 手动LazyLayout 自动测量
状态保持onSaveInstanceStateremember + 保存able
预取GapWorker + prefetchLazyListPrefetchStrategy

🧩 Compose 懒加载机制 LazyLayout 核心

LazyColumn 不会一次性组合所有 item,而是根据 可视区域 + 预取边界 动态组合。 内部使用 LazyListState 控制滚动偏移,通过 LazyLayout 实现按需布局。

LazyListState 滚动偏移 / 锚点 LazyLayout 测量 · 布局 · 预取 SlotTable 组合插槽 · 状态 可视区域 预取缓冲区 回收池 预取 回收 复用

💡 只有进入可视区域 + 预取范围的 item 才会被组合,其余保持未组合状态。

♻️ item 回收与复用 SlotTable & 重组

🧠 Compose 回收复用核心

  • SlotTable 维护每个位置的组合数据 (Composable 节点树)
  • 滚动时 item 滑出屏幕 → 标记为 inactive,但保留状态
  • 滑入屏幕 → 从 SlotTable 中 复用 已有插槽,仅重组内容
  • 使用 key 参数稳定标识,避免状态错乱
  • 回收池基于 LazyListLayoutInfo 控制复用窗口
// 典型 LazyColumn 代码 — 复用关键
LazyColumn {
    items(
        items = list,
        key = { it.id }   // 稳定复用
    ) { item ->
        ListItemCard(item)
    }
}

// 内部 SlotTable 自动管理
// 滑出屏幕: 插槽保留, 内容挂起
// 滑入屏幕: 插槽激活, 重组 @Composable

✅ 使用 key 提升复用稳定性,避免重组闪烁。

阶段行为Compose 内部
1. 滑出可视区item 不再可见SlotTable 标记为 removed,但 Composables 保持
2. 进入预取区即将显示LazyLayout 触发 预组合,复用已有 slot
3. 完全可见item 展示重组 (Recompose) 更新内容,无新分配
4. 远离屏幕超出回收距离SlotTable 释放插槽,资源回收

📦 回收复用示意 滑入 / 滑出

回收池 可视区域 预取区 惰性回收 复用回可视区

♻️ 回收复用循环:滑出 → 回收池 → 预取复用 → 可见