初步理解RecycleView缓存机制

1.recycleView

   官方介绍:A flexible view for providing a limited window into a large data set.
        即:为大数据集提供有限窗口的灵活视图

2.缓存层级

  源码中对相应缓存方法定义初步看有两个方法:
    1. Scrap (view):布局期间进入临时分离状态的子视图。没有完全与父RecycleView完全分离, 
                     如果不需要重新绑定则可以不进行更改,如果视图被认为dirty则可以由适配器进行改。
                    (dirty: A child view that must be rebound by the adapter before being displayed.
                                在展示之前必须被适配器重新绑定的视图,例如一个视图在展示的数据是数据A,但是之后要展示数据B
                                此时就是dirty的视图,重新展示前需要重新绑定数据后再展示)
    2.Recycle (view): 先前用于显示特定适配器位置的数据的视图可以放置在缓存中,以供稍后重用再次显示相同类型的数据
                      可以通过跳过初始布局膨胀或构造来提高性能
                      
  方法是两种缓存类型,但是recycleView是4级缓存,掌握整个缓存最重要的内部类是final class Recycler类
      (定义成final的内部类,不可被继承。,不可被扩展,对象是只读的
       使用final修饰可以提高性能,jvm和java应用都可以缓存final变量;
       final变量可以安全的在多线程下共享,而不需要额外的同步开销;
       使用final关键字,JVM会对变量,方法和类进行优化)
  Recycler类是负责管理报废或分离的item view以用来重用
       (报废view是指仍旧附加于父RecycleView的视图但是已经被标记为删除或重用了)
  Recycler类中有以下的成员变量:
       mAttachedScrap:存放ViewHolder的ArrayList,属于Scrap中的一种,这里的数据是不做修改的,不会重新走Adapter的绑定方法
       mChangedScrap: 存放发生变化的ViewHolder的ArrayList,这里的缓存的ViewHolder是要重新走Adapter的绑定方法的。
       mCachedViews:存放已经remove掉的视图,已经和recycleView分离的关系的视图,但ViewHolder依然保存着之前的信息(默认容量2)
       mRecyclerPool:保存的ViewHolder不仅仅是removed掉的视图,而且是恢复了出厂设置的视图。缓存是按照itemType来分开存储的
       mViewCacheExtension: 这一级缓存是留给开发者自由发挥的,官方并没有默认实现,它本身是null
       因此明了的四级缓存结构:
       Scrap: 对应屏幕内的缓存数据,可以直接复用
         ↓
       Cache: 杠杆移出屏幕的数据,默认大小2.根据position查找,遵循FIFO,先进入的缓存数据移出并放入下一级缓存
         ↓
       ViewCacheExtension: 留给开发者自由发挥的
         ↓
       RecycledViewPool:默认大小5,cache将视图移出缓存到RecycledViewPool,存入之前ViewHolder的数据将被全部重置,
                         缓存是按照itemType来分开存储的,取出时需要走onBindViewHolder()方法

3.RecycleView的加载过程

  正常view经过onMeasure,onLayout, onDraw三个方法加载出来
  正式开始布局时先是调用detachViewAt(index)来分离视图,然后调用了recycler.scrapView(view)方法
  获取view的流程:
  (1)从getChangedScrapViewForPosition(position)方法中找需要的视图,
       数据发生了变化,viewholder被detach掉后缓存在mChangedScrap之中,在这里拿到的viewHolder后续需要重新绑定
  (2)如果没有找到视图则从getScrapOrHiddenOrCachedHolderForPosition这个方法中继续找。
       查找顺序:mAttachedScrap → 前面略过的ChildHelper类中的mHiddenViews → mCachedViews
  (3)从mViewCacheExtension中查找,这个是自定义的,默认null
  (4)从RecyclerPool中查找,先通过itemType从SparseArray类型的mScrap中拿到ScrapData,
       不为空继续拿到scrapHeap这个ArrayList,然后取到视图,这里拿到的视图需要重新绑定。
  (5)如果前面几步都没有拿到视图,那么调用了mAdapter.createViewHolder(RecyclerView.this, type)方法

4.RecycleView滑动时的缓存过程

  mCachedViews是有容量限制的,默认为2。那么如果符合放到mCachedViews中的条件,首先会判断mCachedViews是否已经满了,
     如果满了会通过recycleCachedViewAt(0)方法把最老得那个缓存放进RecyclerPool,然后在把新的视图放进mCachedViews中。
     如果这个视图不符合条件会直接被放进RecyclerPool中。在缓存进mCachedViews之前,我们的视图只是被remove掉了,绑定的数据等信息都还在,
     这意味着从mCachedViews取出的视图如果符合需要的目标视图是可以直接展示的,而不需要重新绑定。
     而放进RecyclerPool最终是要调用putRecycledView方法的,这个方法中同样对容量做了判断,
     如果容量满了,就不再继续缓存了。在缓存之前先调用了scrap.resetInternal()方法,缓存之前把视图的信息都清除掉了
  和从无到有的过程一样,最后滚动也调用了fill方法,那最后必然是要走到前面分析的获取视图的5个流程。
  布局完成之后,Scrap层的缓存就是空的了,那就只能从mCachedViews或者RecyclerPool中取了,都取不到最后就会走onCreateViewHolder创建视图

5.数据更新时的缓存过程

 数据刷新时,推荐使用notifyItemChanged等方法而不使用notifyDataSetChanged方法
      在调用notifyDataSetChanged方法后,所有的子view会被标记,这个标记导致它们最后都被缓存到RecyclerPool中,然后重新绑定数据。
         并且由于RecyclerPool有容量限制,如果不够最后就要重新创建新的视图了。
      使用notifyItemChanged等方法会将视图缓存到mChangedScrap和mAttachedScrap中,这两个缓存是没有容量限制的,
         所以基本不会重新创建新的视图,只是mChangedScrap中的视图需要重新绑定一下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值