众所周知,RecyclerView在android中实现列表是性能非常好的,那么性能好的原因在哪里呢?关键还是在它在处理view时的回收和复用。列表在滑动的时候,会进行itemView的回收和复用,那么我们就从滑动回调即onTouchEvent来入手分析。
基本概念
- ViewHolder: View的容器,一项View就对应一个ViewHolder
- Recyler:RecyclerView的内部类,主要负责View的回收和复用
- LinearLayoutManager: RecyclerView的线性布局管理器
滑动时函数调用链
四级缓存机制
层级 | 缓存变量 | 缓存名 | 容量 | 数据结构 | 缓存用途 |
---|---|---|---|---|---|
1 | mChangeScrap与 mAttachedScrap | 可见缓存 | x | ArrayList | 用于布局过程中屏幕可见表项的回收和复用 |
2 | mCachedViews | 缓存列表 | 2 | ArrayList | 用于移出屏幕表项的回收和复用,不会清空数据 |
3 | mViewCacheExtension | 自定义缓存 | x | ||
4 | RecycledViewPool | 缓存池 | 5 | SparseArray | 用于移出屏幕表项的回收和复用,会将ViewHolder的数据重置 |
回收的关键方法分析
## RecyclerView.java
void recycleViewHolderInternal(ViewHolder holder) {
...
if (forceRecycle || holder.isRecyclable()) {
if (mViewCacheMax > 0
&& !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID
| ViewHolder.FLAG_REMOVED
| ViewHolder.FLAG_UPDATE
| ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN))
// 1) 先尝试放到cacheView中
int cachedViewSize = mCachedViews.size();
if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
// 如果 mCachedViews 已经满了,把第0个位置的移除并放到 缓存池中
recycleCachedViewAt(0);
cachedViewSize--;
}
if (!cached) {
// 2) 如果CacheView中没放进去,