RecycleView缓存

RecyclerView根据不同的状态可以分为:屏幕内缓存、屏幕外缓存、自定义缓存、缓存池。RecyclerView是通过内部类Recycler来管理缓存。
一级缓存:屏幕内缓存(mAttachedScrap)
屏幕内缓存指在屏幕中显示的ViewHolder,这些ViewHolder会缓存在mAttachedScrap、mChangedScrap中 :

mChangedScrap 表示数据已经改变的ViewHolder列表,需要重新绑定数据(调用onBindViewHolder)
mAttachedScrap 未与RecyclerView分离的ViewHolder列表
二级缓存:屏幕外缓存(mCachedViews)
用来缓存移除屏幕之外的 ViewHolder,默认情况下缓存容量是 2,可以通过 setViewCacheSize 方法来改变缓存的容量大小。如果 mCachedViews 的容量已满,则会优先移除旧 ViewHolder,把旧ViewHolder移入到缓存池RecycledViewPool 中。

三级缓存:自定义缓存(ViewCacheExtension)
给用户的自定义扩展缓存,需要用户自己管理 View 的创建和缓存,可通过Recyclerview.setViewCacheExtension()设置。

四级缓存:缓存池(RecycledViewPool )
ViewHolder 缓存池,在mCachedViews中如果缓存已满的时候(默认最大值为2个),先把mCachedViews中旧的ViewHolder 存入到RecyclerViewPool。如果RecyclerViewPool缓存池已满,就不会再缓存。从缓存池中取出的ViewHolder ,需要重新调用bindViewHolder绑定数据。

按照 ViewType 来查找 ViewHolder
每个 ViewType 默认最多缓存 5 个
可以多个 RecyclerView 共享 RecycledViewPool
RecyclerViewPool底层是使用了SparseArray来分开存储不同ViewType的ViewHolder集

列表刷新优化:
对于类似于从列表进详情关注某个用户后,回到列表客户端刷新列表关注状态数据(可能不止当前item需要改变关注状态)
本地刷新,可以通过反射修改缓存数据。
1、直接修改Adapter对应的List数据,但不执行notifyDataSetChanged()方法
2、屏内缓存找到对于ViewHolder直接更新UI
3、瓶外缓存可以通过反射找到对于ViewHolder再更改UI(关键点)
屏外缓存不会触发onBindViewHolder()方法需要手动反射修改UI

4、缓存池不需做任何操作,当滑动到对应item会回调onBindViewHolder方法,然后更改UI

列表页收到广播后直接修改数据和更新UI

屏内缓存可以直接修改

         // 关注状态变化广播
          @Override
           public void onFollowChange(String follow_user_id, int follow_status) {
               if (!hasInit)
                   return;

               if (videoList != null && videoList.size() > 0) {
                   for (int i = 0; i < videoList.size(); i++) {
                       if (follow_user_id.equals(videoList.get(i).getUser_id())) {
                           videoList.get(i).setFollow_status(follow_status);
                           RecyclerView.ViewHolder viewHolder = rc_video_list.findViewHolderForAdapterPosition(i);
                           if (viewHolder != null && viewHolder instanceof VideoAdapter.VideoViewHolder) {
                               VideoAdapter.VideoViewHolder itemHolder = (VideoAdapter.VideoViewHolder) viewHolder;
                               itemHolder.bindDataFollow(type, videoList.get(i));//更新UI
                           }
                       }
                   }
                   RecycleViewCachedViewBindViewUtils.bindView(rc_video_list, new RecycleViewCachedViewBindViewUtils.BindView() {
                       @Override
                       public void bindView(RecyclerView.ViewHolder viewHolder,int positon) {
                           if (viewHolder != null && viewHolder instanceof VideoAdapter.VideoViewHolder) {
                               VideoAdapter.VideoViewHolder itemHolder = (VideoAdapter.VideoViewHolder) viewHolder;
                               itemHolder.bindDataFollow(type,videoList.get(positon));//更新UI
                           }
                       }
                   });
               } else {
                   if (type == Constants.FOLLOW_MV) {
                       initData();
                       return;
                   }
               }
           }

更新屏外缓存UI

package com.aimei.meiktv.util;

import android.support.v7.widget.RecyclerView;
import java.lang.reflect.Field;
import java.util.ArrayList;

/**
 * 更新CachedView里的ViewHoler
 * by  xingchun  2020-12-18
 */
public class RecycleViewCachedViewBindViewUtils {
    public static void bindView(RecyclerView rc_video_list, BindView bindView) {
        try {
            Field field_mRecycler = RecyclerView.class.getDeclaredField("mRecycler");
            field_mRecycler.setAccessible(true);
            RecyclerView.Recycler recycler = (RecyclerView.Recycler) field_mRecycler.get(rc_video_list);
            Field field_mCachedViews = RecyclerView.Recycler.class.getDeclaredField("mCachedViews");//找到屏外缓存
            field_mCachedViews.setAccessible(true);
            ArrayList mCachedViews = (ArrayList) field_mCachedViews.get(recycler);
            if (mCachedViews != null && mCachedViews.size() > 0) {
                for (int i = 0; i < mCachedViews.size(); i++) {
                    RecyclerView.ViewHolder viewHolder = mCachedViews.get(i);
                    bindView.bindView(viewHolder, viewHolder.getAdapterPosition());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public interface BindView {
        void bindView(RecyclerView.ViewHolder viewHolder, int positon);
    }
}

更新UI

  public void bindDataFollow(int type, NewVideoV3 video) {
            if (video==null){
                fv_follow_view.setVisibility(View.GONE);
                return;
            }
            fv_follow_view.bindData(video);
            if ( video.getFollow_status() == 1
                    || video.getFollow_status() == 2
                    || (!TextUtils.isEmpty(AppUtil.getUserId()) && AppUtil.getUserId().equals(video.getUser_id()))) {//关注  (自己或别人的)作品不显示关注
                fv_follow_view.setVisibility(View.GONE);
            } else {//未关注
                fv_follow_view.setVisibility(View.VISIBLE);
            }
        }

你可能感兴趣的:(RecycleView缓存)