RecylcerVIew缓存复用

onCreateViewHolder和onBindViewHolder

当滑动屏幕时,onCreateViewHolder和onBindViewHolder是如何使用的?
判断是否有缓存,没缓存就调用onCreateViewHolder,有缓存就调用onBindViewHolder。

复用机制讲解

了解复用机制的,我们需要知道那开始调用复用机制?
我们使用RecyclerView时,滑动的时候有可能会调用复用机制。
所以我们从onTouchEvent入手,找到down事件 ,找到消费dx,dy–scrollByInternal(int x, int y, MotionEvent ev, int type) 有水平滑动 和垂直滑动的判断。scrollStep(x, y, mReusableIntPair);
我们看垂直滑动 mLayout.scrollVerticallyBy(dy, mRecycler, mState);

  • 这里用策略模式(不同的LayoutManager)和桥接模式(将LayoutManager管理或Recycler的其他业务分开)

进入LinearLayoutManager 的scrollVertically方法 scrollBy(dy, recycler, state); 中如何处理消费事件fill(recycler, mLayoutState, state, false); 填充;
fill中 layoutChunk(recycler, state, layoutState, layoutChunkResult); 中有layoutState.next(recycler);

  • 重点

layoutState.next(recycler)中的返回的View。进入next方法recycler.getViewForPosition(mCurrentPosition);根据当前位置再Recycler中返回View对象。(复用view。)然后tryGetViewHolderForPositionByDeadline(position, dryRun, FOREVER_NS).itemView;
进入这个方法 返回的时ViewHolder。根据ViewHolder来获取View。
第一个getChangedScrapViewForPosition(position);屏幕内的viewholder 根据 id和position获取mChangedScrap是RecyclerView保存的ArrayList集合(当前数据,即屏幕内数据)add方法中(屏幕内没移除标记 ,但需要更新,不可以重复利用的View,要走绑定方法)
如果holder为空,进入第二个方法
第二个方法getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);中调用mAttachedScrap.get(i)和mCachedViews.get(i),通过位置position获取ViewHolder。mAttachedScrap的add方法是在ViewHolder的remove移除标记,invalid无效标记,!isUpdated没有更新和canReuseUpdatedViewHolder(holder)重复利用可以是添加的。(屏幕内移除标记不需要更新,可以重复利用的View)。mCachedViews缓存View的add方法是在上面的相同事件添加的,而且它初始化了容量大小为2。(回收viewHolder里调用该方法,当容量大于二时,先把第一个移除,第二个+1,将新的移到第二个位置 ,实现先进先出(队列)的效果)
如果holder为空则进入第三个方法。
第三个方法getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition)通过 mAttachedScrap.get(i)和mCachedViews.get(i),通过位置id来获取ViewHolder
如果没有进入第四个方法
mViewCacheExtension.getViewForPositionAndType。自定义缓存类
如果没有进入第五个方法、
getRecycledViewPool().getRecycledView(type)缓存池中。mScrap的数据类型为SparseArray,通过SparsArray来保存数据(int,object)的map集合保存数据。通过 viewType来获取相应的ScrapData中来获取ViewHolder,定义最大容量为5的缓存池。通过多布局的类型来获取相应的ScrapData的ViewHolder.
如果没有则创建ViewHolder
mAdapter.createViewHolder(RecyclerView.this, type);

  • 简而言之:RecylcerView通过判断四级缓存是否有ViewHolder,没有ViewHolder则创建。
    mChangeScrap和mAttachScrap 用来缓存还在屏幕内的ViewHolder( 股票市场App用到)
    mCachedView 用来缓存移除屏幕之外的ViewHolder(2个)
    mViewCacheExtension 这个创建缓存有开发者控制,系统未往着添加数据
    RecyclerViewPool ViewHolder缓存池 (5个)

缓存机制

先缓存,再复用
onLayout—dispatchLayout()
dispatchLayoutStep1(); dispatchLayoutStep2(); dispatchLayoutStep3();
dispatchLayoutStep2();---- mLayout.onLayoutChildren(mRecycler, mState);- --detachAndScrapAttachedViews(recycler);—scrapOrRecycleView(recycler, i, v);–recycler.recycleViewHolderInternal(viewHolder);—满了先移除再添加缓存池。

mCacheView的缓存策略:如果size等于2,先将0的位置回收,并将它丢入缓存池,然后判断该viewType是否满了(等于5),如果满了则不需要添加直接return,如果先将ViewHolder的信息置空,在丢入缓存池,然后移除0的位置数据。size-1;然后将1的位置的缓存推向0位置,然后在1的位置添加新的缓存。

数据结构类型

CacheView为 先进先出的队列
Pool为SparseArray数组(类似HashMap(key为viewType,value为空的ViewHolder))

总结

采用了享元设计模式,防止频繁创建。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值