RecyclerView缓存机制

RecyclerView缓存机制

对于RecyclerView的缓存机制,首先要考虑一下几个问题:

  1.  回收什么?复用什么?
  2.  回收到哪里去?从哪里获得复用?
  3.  什么时候回收?什么时候复用?

带着这几个问题,去看源码,相信如果能准确的回答这几个问题,那么对RecyclerView的回收机制,基本就了解清楚了。

 回收什么?复用什么?

先回答这个问题,回收的是ViewHolder,复用的也是ViewHolder

 回收到哪里去?从哪里获得复用?

这个分为两部分:

1,回收到哪里去?

我个人习惯定义为四级缓存:

  1. mChangeScrap与 mAttachedScrap,用来缓存还在屏幕内的 ViewHolder
  2. mCachedViews,用来缓存移除屏幕之外的 ViewHolder 
  3. mViewCacheExtension,开发给用户的自定义扩展缓存,需要用户自己管理 View 的创建和缓存
  4. RecycledViewPool,ViewHolder 缓存池,它的数据都是从mCachedViews中转移过来的

回收,就是把ViewHolder回收到以上四级缓存中去,这四级缓存都是用来存放ViewHolder的集合。

2,从哪里获得复用?

获得复用,也就是从上面四级缓存中,获得保存的ViewHolder,展示在RecyclerView列表中。

 3,什么时候回收?什么时候复用?

这个点是最关键的,要了解触发缓存回收的动作是什么,什么时候需要RecyclerView去从缓存中获取这些ViewHolder进行复用。

关于这个问题,从以下几点着手分析:

  1. 系统绘制RecyclerView时
  2. 滑动RecyclerView时
  3. 当RecyclerView列表中,有某些或者某个单独的Item发生变化,需要通过Adapter的notifyxxx方法更新界面的时候

以上这三点都会触发回收,其中3在触发回收的时候,同时也是从缓存中获取ViewHolder进行复用的时候。

3.1系统绘制RecyclerView时回收

系统绘制RecyclerView时,onMeasure-->onLayout-->onDraw,无非就是这几个方法,看源码流程,大概如下:

onLayout-->dispatchLayout-->dispatchLayoutStep2-->LinearLayoutManager.onLayoutChildren --> detachAndScrapAttachedViews --> scrapOrRecycleView

//从这里开始,主要分为两个分支:

--> 1.recycler.recycleViewHolderInternal(viewHolder); -- 处理 CacheView 、RecyclerViewPool 的缓存

      --> 1.1 ViewHodler改变 不会进来 -- 先判断mCachedViews的大小

      --> mCachedViews.size 大于默认大小 --- recycleCachedViewAt ​ --- >addViewHolderToRecycledViewPool --- 缓存池里面的数据都是从mCachedViews里面出来的

      --> 1.2 addViewHolderToRecycledViewPool --> getRecycledViewPool().putRecycledView(holder);

      --> scrap.resetInternal(); ViewHolder 清空

--> 2.recycler.scrapView(view);

下面是这整个过程的时序图:

RecyclerView绘制时,缓存回收时序图
RecyclerView绘制时,缓存回收时序图

3.2滑动RecyclerView时,会有复用,复用的时候也就是从四级缓存的几个集合中去获取ViewHolder进行复用

滑动 Move 事件,OnTouch --> scrollByInternal --> scrollStep --> mLayout.scrollVerticallyBy --> scrollBy --> fill --> layoutChunk --> layoutState.next --> addView(view);

layoutState.next --> getViewForPosition --> tryGetViewHolderForPositionByDeadline -->

怎么从集合中去获取:tryGetViewHolderForPositionByDeadline,分几种情况去获取ViewHolder

  1. getChangedScrapViewForPosition -- mChangeScrap 与动画相关

  2. getScrapOrHiddenOrCachedHolderForPosition -- mAttachedScrap 、mCachedViews

  3. getScrapOrCachedViewForId -- mAttachedScrap 、mCachedViews (ViewType,itemid)

  4. mViewCacheExtension.getViewForPositionAndType -- 自定义缓存 -- (使用情况:局部刷新??)

  5. getRecycledViewPool().getRecycledView -- 从缓冲池里面获取, RecycledViewPool -- 缓存池

     6.当没有缓存的时候---> mAdapter.createViewHolder --> onCreateViewHolder

多级缓存的目的 -- 为了性能

创建ViewHolder 后 绑定: tryBindViewHolderByDeadline--> mAdapter.bindViewHolder-->onBindViewHolder

整个流程调用时序图如下:

RecyclerView滑动时,复用缓存中ViewHolder

 

3.3 当RecyclerView列表中,有某些或者某个单独的Item发生变化,需要通过Adapter的notifyxxx方法更新界面的时候

主要流程如下:notifyDataSetChanged-->mObservable.notifyChanged --> (RecyclerViewDataObserver)mObservers.get(i).onChanged --> requestLayout

流程调用时序图:

RecyclerView中notifyxxxChanged时,缓存回收图

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值