RecyclerView理解-布局与回收复用、ListView和RecyclerView的区别

【腾讯Bugly干货分享】Android ListView 与 RecyclerView 对比浅析—缓存机制

ListView和RecyclerView的区别

RecyclerView和ListView的区别

RecyclerView理解-布局与回收复用

自定义控件三部曲视图篇(七)——RecyclerView系列之四实现回收复用

RecyclerView回收和复用机制最全分析

RecyclerView的回收复用由模块Recycler来负责,其设计了4层缓存,
按照使用的优先级顺序依次是

  • mAttachedScrap ( onLayoutChildren方法中调用detachAndScrapAttachedViews(recycler) )
  • mCachedViews (scrollVerticallyBy/scrollHorizontallyBy 方法中调用removeAndRecycleView(child, recycler),默认2个 )
  • mViewCacheExtension ( ViewCacheExtension默认是没有实现的,预留给开发者针对自己的项目实际使用。)
  • mRecyclerPool (按照viewtype将以上尚未存储的进行存储)

Recycler:

public final class Recycler {
    //1
    final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
    ArrayList<ViewHolder> mChangedScrap = null;

    //2
    final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();

    private final List<ViewHolder>
            mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);

    private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;
    int mViewCacheMax = DEFAULT_CACHE_SIZE;

    //3
    RecycledViewPool mRecyclerPool;

    //4
    private ViewCacheExtension mViewCacheExtension;

    static final int DEFAULT_CACHE_SIZE = 2;
}
Scrap

scrap 英 [skræp] 美 [skræp]
n. 碎片,小块(纸、织物等); 丝毫; 一丁点; 残羹剩饭

Scrap是RecyclerView中最轻量的缓存,它不参与滑动时的回收复用,只是作为重新布局时的一种临时缓存。
它的目的是,缓存当界面重新布局的前后都出现在屏幕上的ViewHolder,以此省去不必要的重新加载与绑定工作。

Scrap实际上包括了两个ViewHolder类型的ArrayList。

重新布局临时缓存, 【显示在屏幕中】,【不会createViewHolder和bindViewHolder】

  • mAttachedScrap : 负责保存将会【原封不动】的ViewHolder,如:初始化时,或者移除其他item自己没动
  • mChangedScrap : 负责保存【位置会发生移动】的ViewHolder,注意只是位置发生移动,内容仍旧是原封不动的。

在layoutmanager的onLayoutChildren初始布局时:使用 detachAndScrapAttachedViews(recycler)将所有的可见HolderView存储到mAttachedScrap

mCachedViews

mCachedViews: 【位置移出屏幕进行的缓存】,【默认缓存2个】,【不会createViewHolder和bindViewHolder】
CacheView是一个以ViewHolder为单位,负责在RecyclerView列表位置产生变动的时候,对刚刚移出屏幕的View进行回收复用的缓存列表。

removeAndRecycleView(child, recycler)

这个函数仅用于滚动的时候,在滚动时,我们需要把滚出屏幕的HolderView标记为Removed,
这个函数的作用就是把已经不需要的HolderView标记为Removed。
想必大家在理解了上面的回收复用原理以后,也知道在我们把它标记为Removed以后,系统做了什么事了。
在我们标记为Removed以为,会把这个HolderView移到mCachedViews中,如果mCachedViews已满,就利用先进先出原则,
将mCachedViews中老的holderView移到mRecyclerPool中,然后再把新的HolderView加入到mCachedViews中。

在滚动时,所有移除的View都是使用removeAndRecycleView(child, recycler),
千万不要将它与detachAndScrapAttachedViews(recycler)搞混了。
在滚动时,已经超出边界的HolderView是需要被回收的,而不是被detach。
detach的意思是暂时存放,立马使用。
很显然,我们这里在越界之后,立马使用的可能性不大,所以必须回收。
如果立马使用,它会从mCachedViews中去取。

大家也可以简单的记忆,在onLayoutChildren函数中(布局时),就使用detachAndScrapAttachedViews(recycler),
在scrollVerticallyBy函数中(滚动时),就使用removeAndRecycleView(child, recycler),当然能理解就更好啦。

mRecyclerPool

mRecyclerPool : 以ViewHolder的viewType来缓存,【默认缓存5个】,【会bindViewHolder】,
mCachedViews超出上限后执行mRecyclerPool存储,即Scrap和cache不存储之后执行pool存储。

RecycledViewPool:

public static class RecycledViewPool {
    private static final int DEFAULT_MAX_SCRAP = 5;

    static class ScrapData {
        final ArrayList<ViewHolder> mScrapHeap = new ArrayList<>();
        int mMaxScrap = DEFAULT_MAX_SCRAP;
        long mCreateRunningAverageNs = 0;
        long mBindRunningAverageNs = 0;
    }
    SparseArray<ScrapData> mScrap = new SparseArray<>();

    private int mAttachCount = 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值