美文网首页
RecyclerView缓存机制

RecyclerView缓存机制

作者: HelloLeol | 来源:发表于2023-08-17 01:02 被阅读0次

RecyclerView缓存机制

在介绍所有的缓存之前需要隆重介绍recyclerview复用机制的核心tryGetViewHolderForPositionByDeadline

ViewHolder tryGetViewHolderForPositionByDeadline(int position,boolean dryRun, long deadlineNs) {
    // 0) If there is a changed scrap, try to find from there
    if (mState.isPreLayout()) {
        holder = getChangedScrapViewForPosition(position);
        fromScrapOrHiddenOrCache = holder != null;
    }
    // 1) Find by position from scrap/hidden list/cache
    if (holder == null) {
        holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
    }
    if (holder == null && mViewCacheExtension != null) {
        final View view = mViewCacheExtension.getViewForPositionAndType(this, position, type);
    }
    if (holder == null) {
        holder = getRecycledViewPool().getRecycledView(type);
    }
}

通过上面代码片段可以看到recyclerview为了复用一共准备了四处缓存

mAttachedScrap mCachedViews mViewCacheExtension mRecyclerPool

mAttachedScrap & mChangedScrap

AttachedScrap 查询网络上已有的资料,大多数博文只会说这个缓存是用来存储界面当前正在展示的viewholder。从attachedScrap中获取到的viewholder在使用的时候不需要重新创建view也不需要重新绑定数据。

但是仔细一想,为什么处于界面之中的viewholder却要有一个缓存池来进行储存了,更何况大部分时间里该scrap一直都是空的,可当前界面明明就有viewholder展示。

为了搞懂这个问题,重新查看了源码发现,recyclerview实际上只会在view被detach的时候才会存入scrapView,比如调用了notifyXXX方法。

调用notifyItemChanged/Removed或者notifyItemRangeChanged后,被标记为删除的viewholder将会被丢入changeScrap。在此scarp中的viewholder将在下一次layout中被拿出来执行动画。当然不是所有的情况都会丢入changedScrap,当以下情况中不需要动画就不会被放入changedScrap

setSupportsChangeAnimations(false)。

notifyDataSetChanged 而不是 notifyItemChanged 或 notifyItemRangeChanged

notifyItemChanged(index,anyObject)。

mCachedViews

相比较上面的scrap,cachedViews则更加接近缓存一点。cachedView默认大小为2,当页面划动时,逐步从页面内划走的则会viewholder则会依次进入cache。处在cachedview中的viewholder不会再需要绑定或者创建。

但是,这些viewholder依旧会执行onViewAttachedToWindowonDetachFromWindow

此外,cachedview还会存储pre-layout出来的viewholder。且当有pre-layout完成时,recyclerview会修改cachedviewSize,所以pre-layout出来的holder不会占用设置给cachedView的默认大小。

当cacheview存满时,viewholder则会按照先进先出的顺序,一次进入下一级缓存 recyclerPool。

ViewCacheExtension

viewcacheExtension是完全给开发者开放出来的,recyclerview没有给任何的默认实现,只负责取出展示。所以具体的缓存规则包括存入的时机都需要开发者自己完成。

特殊的点是,viewCacheExtension返回的是view,然后从view中的layoutParams中取出viewholder。

然后viewholder本身会存储一些flag,这些flag被recycerview管理。如果没有管理很好会造成crash。

至于具体实现在网上很少有优秀的实践例子,不到万不得已都不推荐使用该拓展。

mRecyclerPool

recyclerPool是实际过程里这几种缓存中使用频率最高的缓存。cacheview中存不下的viewholder就会被存在这里。recyclerPool默认每一种type类型的viewhodler最多存储5个,对于存不下的viewholder则会进行丢弃。存在pool中的holder拿出来后不需要进行再次createView,但是任然需要进行bindholder来进行数据绑定。但其实已经会节省大部分时间提高系统的流畅度了。

总结

recyclerview的各种缓存需要结合具体的实际情况,进行合适的调用与调整,在内存和效率间取到一个平衡。如果贸然的增大缓存可能会得不偿失,但不好好利用缓存机制,应用又会非常卡顿,本文只是简单介绍了缓存,recyclerview还有pre-load机制、viewcacheExtension细节等。也依旧值得去继续学习。

相关文章

网友评论

      本文标题:RecyclerView缓存机制

      本文链接:https://www.haomeiwen.com/subject/npplmdtx.html