ListView的生命周期

0 阅读1分钟

下面将会系统性分析Android中ListView的生命周期与内部机制。重点参考了AbsListView和RecycleBin源码,从以下方面展开说明:

  1. 初始化阶段:ListView在创建时的布局测量、子视图生成逻辑。

  2. 数据绑定机制:Adapter数据与视图的绑定过程及相关回调方法。

  3. 更新流程:数据变化后ListView如何刷新、重绘与重用子视图。

  4. 回收与复用机制:RecycleBin在视图缓存与复用中的作用、回收策略与效率优化。

  5. 释放与销毁:ListView在滑动或销毁过程中的资源管理与内存释放方法。

一、初始化阶段:创建、测量与子视图生成

1. 类层级与职责划分

View
 └── ViewGroup
     └── AdapterView
         └── AbsListView
             └── ListView
  • AdapterView:定义 Adapter 数据驱动视图的抽象行为

  • AbsListView:实现滚动、复用、选择、回收等核心机制

  • ListView:实现线性垂直布局(一个接一个)

2. 构造与初始化流程

AbsListView 构造函数中完成核心初始化:

public AbsListView(Context context, AttributeSet attrs, int defStyleAttr)

关键初始化内容:

  • 创建 RecycleBin mRecycler

  • 初始化滚动相关对象(Scroller / OverScroller)

  • 设置 CacheHint、FadingEdge、Selector

  • 初始化触摸、速度追踪器等

✅ 设计思想:

在构造阶段完成“可复用基础设施”的搭建,而不是创建任何 Item View。

3. 测量与布局入口

测量阶段

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
  • AbsListView 并 不会在 onMeasure 中创建所有子 View

  • 只确定自身尺寸(match_parent / wrap_content)

  • Item 的测量延后到布局阶段

布局阶段

protected void onLayout(boolean changed, int l, int t, int r, int b)

内部会调用:

layoutChildren();

这是 ListView 真正开始创建 / 复用子 View 的地方。

4. layoutChildren 核心流程(简化)

void layoutChildren() {
    // 1. 将当前子 View 移交给 RecycleBin
    mRecycler.fillActiveViews(childCount, mFirstPosition);
    detachAllViewsFromParent();

    // 2. 根据 mFirstPosition 向下填充可见区域
    fillFromTop();

    // 3. 将未复用的 ActiveViews 转入 ScrapViews
    mRecycler.scrapActiveViews();
}

✅ 关键点:

  • 不会一次性创建所有 Item

  • 只填充“屏幕可见 + 少量缓存”的 View

二、数据绑定机制:Adapter → View

1. Adapter 绑定入口

setAdapter(ListAdapter adapter)

内部流程:

  • 注册 DataSetObserver

  • 清空旧 View

  • 清空 RecycleBin

  • 触发 requestLayout()

2. 获取 Item View 的统一入口

View obtainView(int position, boolean[] isScrap)

执行逻辑(核心):

  1. TransientState View 获取(动画、临时状态)

  2. RecycleBin.getScrapView(position) 获取

  3. 若没有可用缓存 → 调用 adapter.getView()

    View child = mAdapter.getView(position, convertView, this);

✅ getView 的核心职责:

  • 将 position 对应的数据绑定到 View

  • 尽量复用 convertView

3. ViewType 与复用安全

int getItemViewType(int position)
int getViewTypeCount()
  • RecycleBin 按 ViewType 分组缓存

  • 避免不同布局错误复用

✅ 性能关键点:

ViewType 决定了缓存池的隔离边界

三、更新流程:数据变化后的刷新机制

1. 数据变更触发

adapter.notifyDataSetChanged();

DataSetObserver.onChanged()

2. AbsListView 响应数据变化

handleDataChanged();
requestLayout();
invalidate();
  • mDataChanged = true

  • 下一次 layoutChildren 时:

    • 不复用 ActiveViews

    • 全部子 View 进入 Scrap

    • 重新从 Adapter 绑定数据

3. 局部 vs 全量刷新

ListView 不支持精细化刷新(与 RecyclerView 的区别):

  • notifyDataSetChanged → 几乎重走 layout

  • View 对象仍可复用

✅ 优化建议:

  • 使用稳定 ID:hasStableIds()

  • 减少 notify 调用频率

四、回收与复用机制:RecycleBin 深度解析

1. RecycleBin 的两级缓存结构

class RecycleBin {
    View[] mActiveViews;
    ArrayList<View>[] mScrapViews;
}

缓存级别

含义

ActiveViews

本次 layout 前屏幕上可见的 View

ScrapViews

已离屏、可复用的 View(按 ViewType)

2. 回收流程

滚动时

addScrapView(child, position)

触发条件:

  • View 完全离开可见区域

  • 数据未发生变化

layout 结束

scrapActiveViews()

将未复用的 ActiveViews 移入 ScrapViews

3. 获取缓存 View

View getScrapView(int position)

策略:

  1. 优先找 相同 position

  2. 再取 同 ViewType 的最后一个

  3. 找不到返回 null

✅ 设计目标:

在正确性前提下,最大化 View 复用概率

4. 性能优化设计

  • O(1) 复用路径

  • 按 ViewType 分桶

  • 避免重复 inflate

  • ViewHolder 模式减少 findViewById

五、释放与销毁:资源管理与内存安全

1. 滑动过程中的释放

  • 离屏 View → addScrapView

  • 清理临时状态:

    child.clearAccessibilityFocus();
    child.onStartTemporaryDetach();
    

2. Adapter 更换 / ListView 销毁

setAdapter(null);

内部执行:

  • 注销 DataSetObserver

  • mRecycler.clear()

  • removeAllViewsInLayout()

3. RecycleBin.clear()

public void clear() {
    for (ArrayList<View> scrap : mScrapViews) {
        scrap.clear();
    }
}

✅ 效果:

  • 解除 View 引用

  • 防止 Context / Activity 泄漏

  • 交由 GC 回收

六、整体性能设计总结

ListView 的核心设计哲学可以概括为:

用最少的 View,承载无限的数据

关键手段包括:

  • 延迟创建(按需填充)

  • 两级缓存(Active + Scrap)

  • ViewType 隔离

  • Adapter 驱动 + Observer 监听

  • 滚动过程中只做“位移 + 少量增删”

七、对比性总结(一句话)

ListView 是一个以 AbsListView + RecycleBin 为核心、通过 View 复用来实现高效滚动的大数据列表容器,其性能上限高度依赖 Adapter 的实现质量。

图示:

参考信息

  1. ListView缓存RecycleBin 解析原创 - CSDN博客

  2. ListView回收机制相关分析 - 阿里云开发者社区

  3. Android-RecyclerView原理 - 知乎专栏

  4. 事件传递机制分析 - 稀土掘金

  5. Android设计模式之适配器模式和应用场景详解 - 51CTO