RecycleView的缓存机制
⼀、Recyclerview的缓存类
RecycleView的四级缓存是由三个类共同作⽤完成的,Recycler、RecycledViewPool和ViewCacheExtension。Recycler⽤于管理已经废弃或者与RecyclerView分离的ViewHolder,这⾥⾯有两个重要的成员,为可以看见的屏幕的内部缓存成员mAttachedScrap、mChangedScrap和滑出屏幕外的外部缓存成员mCachedViews⼆者共同完成ViewHolder的缓存;RecycledViewPool类是⽤来缓存整体所有的ViewHolder,是对mCachedViews缓存的补充;ViewCacheExtension是扩展内的缓存对象,默认不加载,需实现⽅法getViewForPositionAndType(Recycler recycler, int position, int type)来实现⾃⼰的缓存。接下来对四级缓存⼀步步介绍。
⼆、Recycler屏幕内部缓存
上⾯说过屏幕内部缓存包括两个重要的成员mAttachedScrap、mChangedScrap。mChangedScrap表⽰数据已经改变的viewHolder列表,mAttachedScrap表⽰未与RecyclerView分离的ViewHolder列表,他是Recycleview的⼀级缓存,缓存查找中不会调⽤Recycleview⽅法onBindViewHolder()。
public final class Recycler {
/
/⼀级缓存中⽤来存储屏幕中显⽰的ViewHolde
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
ArrayList<ViewHolder> mChangedScrap = null;
//⼆级缓存中⽤来存储屏幕外的缓存
final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
//暂可忽略 mAttachedScrap的不可变视图
private final List<ViewHolder> mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);
//当前屏幕外缓存⼤⼩,数量为2
private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;
int mViewCacheMax = DEFAULT_CACHE_SIZE;
//四级缓存当⼆级缓存超过2时候启⽤
RecycledViewPool mRecyclerPool;
//三级缓存扩展类(默认不启⽤)
private ViewCacheExtension mViewCacheExtension;
static final int DEFAULT_CACHE_SIZE = 2;
}
1、内部缓存的添加
void scrapView(View view) {
//根据View获取ViewHolder
final ViewHolder holder = getChildViewHolderInt(view);
//判断该ViewHolder是否分离
if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)
|| !holder.isUpdated() || canReuUpdatedViewHolder(holder)) {
if (holder.isInvalid() && !holder.isRemoved() && !mAdapter.hasStableIds()) {
throw new IllegalArgumentException("Called scrap view with an invalid view."高中政治书
+ " Invalid views cannot be reud from scrap, they should rebound from"
+ " recycler pool." + exceptionLabel());
}
//未分离的ViewHolder设置fal
holder.tScrapContainer(this, fal);
//添加到未分离的集合mAttachedScrap⾥⾯
mAttachedScrap.add(holder);
} el {
if (mChangedScrap == null) {
mChangedScrap = new ArrayList<ViewHolder>();
}
//如果已经分离设置ViewHolder为true
holder.tScrapContainer(this, true);
//添加到已经分离的集合mChangedScrap⾥⾯
mChangedScrap.add(holder);
}
}
三、Recycler屏幕外部缓存沿途的风景的经典语录
屏幕的外部缓存是⼆级缓存,使⽤的缓存容器变量是mCachedViews,缓存最近回收的ViewHolder,
缓存复⽤时必须匹配position,这个集合⾥存的 ViewHolder 的原本数据信息都在,所以可以直接添加到 RecyclerView 中显⽰,不需要再次重新onBindViewHolder()。默认⼤⼩是2,最⼤的缓存⼤⼩默认为2个ViewHolder,可以通过Recycleview的tViewCacheSize⽅法进⾏设置缓存⼤⼩。
含义深刻的句子public void tViewCacheSize(int viewCount) {
mRequestedCacheMax = viewCount;
updateViewCacheSize();
}
糊里糊涂的近义词如果缓存满了的话,就会移除最后⼀个缓存的缓存加到四级缓存的缓冲池中:
void recycleCachedViewAt(int cachedViewIndex) {bdbd
//cachedViewIndex为缓存容器mCachedViews的mCachedViews.size() - 1
ViewHolder viewHolder = (cachedViewIndex);
//添加进缓存池
addViewHolderToRecycledViewPool(viewHolder, true);
//移除缓存容器mCachedViews中该ViewHolder
}
四、ViewCacheExtension缓存
ViewCacheExtension缓存是⾃定义的缓存三级缓存,是⼀个Recycleview的⼀个抽象的静态内部内留,给开发者开发,需要直线getViewForPositionAndType抽象⽅法,默认不会加载,这⾥不详细说明:
public abstract View getViewForPositionAndType(Recycler recycler, int position, int type);
五、RecycledViewPool缓存
吉他大横按
void clear() 清空缓存池
RecyclerView.ViewHolder getRecycledView(int viewType) 得到⼀个viewType类型的Item
void putRecycledView(RecyclerView.ViewHolder scrap) 把viewType类型的Item放⼊缓存池 void tMaxRecycledViews(int viewType, int max)设置对应viewType类型的Item的最⼤缓存数量
这⾥看看常⽤的tMaxRecycledViews⽅法:
女生生日RecyclerView.RecycledViewPool pool = RecycledViewPool();
pool.tMaxRecycledViews(0,10);
//如果LayoutManager是LinearLayoutManager GridLayoutManager,则需要tRecycleChildrenOnDetach(true)
//layoutManager.tRecycleChildrenOnDetach(true);
recyclerView.tRecycledViewPool(pool);
Recycleview的四级缓存图总结如下:
六、Recycleview的缓存引起的错乱问题
Recycleview的缓存虽然功能强⼤,但是有些时候缓存复⽤能导致页⾯布局错位,异常,问题出现后通常有以下⽅法解决:
1、ViewHolder的tIsRecyclable⽅法
使⽤ViewHolder的tIsRecyclable⽅法可以使禁⽌该ViewHolder的缓存,每个页⾯都是新的,这种⽅法简单、快捷,但是也⼗分暴⼒数据量⼤的话会导致滑动顿卡,数据量⼩的话效果不错。他的原理是通过设置标志位,使其忽略⼀切缓存。
holder.tIsRecyclable(fal);
2、Recycleview的tViewCacheSize⽅法
通过设置tViewCacheSize的⼤⼩可以扩⼤或者缩⼩屏幕外的缓存数量,来改善异常问题。
recyclerView.tItemViewCacheSize(0);//禁⽤屏幕外缓存,直接使⽤RecycledViewPool缓存
recyclerView.tItemViewCacheSize(20);//扩⼤屏幕外缓存
3、 Recycleview的tRecycledViewPool⽅法
爱国主题演讲稿
通过设置指定类型的ViewHolder的缓存池中能缓存的数量来限制。
pool.tMaxRecycledViews(0,0);//TYPE为0,缓存数量为0
recyclerView.tRecycledViewPool(pool);//给Recycleview设置缓存池对象
4、通过新增⼀个boolean类型变量维护在接⼝返回数据Bean类中
每次选中或者点击设置数据的布尔值为true,⾮选中或者执⾏状态置为fal,这样每次的UI展⽰都是根据接⼝维护数据来判断,不会引起错位问题。
5、通过内部维护Map集合
将选中和⾮选中的状态存储在Map集合中,位置position作为key,状态作为value,每次UI展⽰操作都从集合中获取position对应,的值,进⾏状态重置。
总结:
RecyclerView的四级缓存包括:
1. ⼀级缓存:mAttachedScrap、mChangedScrap
2. ⼆级缓存:mCacheViews
3. 三级缓存:mViewCacheExtension
4. 四级缓存:mRecyclerPool
⼀级缓存为屏幕内缓存,⼆级缓存为屏幕外缓存,三级缓存为⾃定义缓存,四级缓存为缓存池缓存。⼀⼆三即缓存直接不需要重新绑定View,四级缓存需要绑定Holder设置数据。禁⽤缓存可以使⽤ViewHolder的tIsRecyclable⽅法。
参考⽂献: