RecycleView系列九:缓存机制和ViewHolder

121 阅读4分钟

RecyclerView缓存机制梳理

RecyclerView为了提高列表滚动时的性能,设计了一套高效的缓存机制,主要通过多级缓存来复用和存储视图。以下是该缓存机制的具体工作方式:

1. Scrap Cache(废弃缓存)

  • mAttachedScrap
    • 存储当前屏幕中但即将被移除的ViewHolder。
    • 这些ViewHolder仍与RecyclerView的父布局保持连接,但已不可见。
    • 查找可重用ViewHolder的首选位置。

2. View Cache(视图缓存)

  • mCachedViews
    • 存储已从屏幕上移除但状态未变的ViewHolder。
    • 默认大小为2,可自定义。
    • 当mAttachedScrap无可用ViewHolder时,从此处查找。
    • 遵循FIFO原则管理缓存大小。

3. 开发者自定义缓存

  • mViewCacheExtension
    • 可选缓存层,允许开发者自定义缓存策略。
    • 适用于需要特殊缓存逻辑的高级场景。

4. RecyclerViewPool(回收池)

  • mRecyclerPool
    • 缓存Item的最终站,保存Removed、Changed及mCachedViews溢出项。
    • 使用SparseArray按ViewType存储ArrayList。
    • 每个ArrayList默认最多存5个ViewHolder。
    • ViewHolder在回收时清理内部数据,需重新绑定。

缓存查找顺序

  1. mAttachedScrap:查找刚剥离的ViewHolder。
  2. mCachedViews:进行精确匹配查找。
  3. mRecyclerPool:从回收池中查找。
  4. createViewHolder:若缓存中无可用ViewHolder,则创建新的。

优化策略

  • 减少视图层级、预加载、共享视图等策略可进一步提升性能。

拓展一:关于ViewHolder

ViewHolder是Android开发中RecyclerView控件的一个重要组件,它主要用于缓存和复用列表项的视图,以提高列表的滚动性能和流畅度。以下是对ViewHolder的详细解释:

定义与功能

  • 定义:ViewHolder是一个静态的内部类,通常继承自RecyclerView.ViewHolder。它用于缓存每个列表项(item)的视图(View)对象,以避免在滚动时重复调用findViewById()方法,从而提高性能。
  • 功能
    1. 缓存视图:ViewHolder通过持有列表项的视图对象,实现视图的缓存。当列表项滚出屏幕后,其对应的ViewHolder会被保存起来,以便后续复用。
    2. 减少findViewById调用:在RecyclerView的onBindViewHolder()方法中,通过ViewHolder可以直接访问到列表项的视图对象,而无需每次都调用findViewById()来查找视图,从而减少了不必要的查找操作,提高了性能。
    3. 支持复杂布局:ViewHolder可以支持复杂的列表项布局,通过绑定不同的视图和数据,实现多样化的列表项展示。

使用方式

  • 定义ViewHolder:通常会在RecyclerView的Adapter中定义一个静态的内部类ViewHolder,并在其中定义与列表项视图相关的字段和方法。
  • 创建ViewHolder:在Adapter的onCreateViewHolder()方法中,通过LayoutInflater加载列表项的布局文件,并将其传递给ViewHolder的构造函数,从而创建ViewHolder实例。
  • 绑定ViewHolder:在onBindViewHolder()方法中,将ViewHolder与特定的数据项绑定,并更新视图以显示这些数据。

示例代码

以下是一个简单的ViewHolder示例代码:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    private List<String> mData;

    public MyAdapter(List<String> data) {
        mData = data;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.my_list_item, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        String item = mData.get(position);
        holder.myTextView.setText(item);
    }

    @Override
    public int getItemCount() {
        return mData.size();
    }

    public static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView myTextView;

        public MyViewHolder(View itemView) {
            super(itemView);
            myTextView = itemView.findViewById(R.id.my_text_view);
        }
    }
}

在这个示例中,MyViewHolder类继承自RecyclerView.ViewHolder,并持有一个TextView的引用。在onCreateViewHolder()方法中,我们加载了列表项的布局文件,并将其传递给MyViewHolder的构造函数。在onBindViewHolder()方法中,我们将ViewHolder与特定的数据项绑定,并更新了TextView的文本内容。

总结

ViewHolder是RecyclerView中用于缓存和复用列表项视图的重要组件。通过减少findViewById()的调用次数和支持复杂布局,ViewHolder显著提高了列表的滚动性能和用户体验。在Android开发中,合理使用ViewHolder是优化RecyclerView性能的关键之一。

拓展二:Android三级缓存策略

Android应用中常见的三级缓存策略用于管理图片等资源,以提高性能和用户体验:

  1. 内存缓存

    • 优先级最高,速度最快。
    • 加载图片时首先检查内存缓存。
  2. 本地缓存

    • 内存缓存未命中时,尝试从本地(如SD卡)加载。
    • 速度次于内存缓存,但可作为备选方案。
  3. 网络缓存

    • 优先级最低,从网络下载图片。
    • 受网络状况影响,速度最慢。

注意事项

  • 缓存的清理和管理至关重要,避免占用过多存储空间或造成内存泄漏。
  • 合理的缓存策略能显著减少不必要的网络请求,提升应用性能。

通过结合RecyclerView的缓存机制和Android的三级缓存策略,开发者可以构建出高效、流畅的用户界面。