RecyclerViewHelper原码解析

来源:互联网 发布:windows 确认证书 编辑:程序博客网 时间:2024/05/18 00:00
RecyclerViewHelper是RecyclerView 的工具类,可以更方便的实现 Adapter,item 点击事件,更快的实现加载提示,分页加载。
首先我们来看看demo
先是MainActivity

    private RecyclerView list_container;    private List<String> dataList;    private ListAdapter listAdapter;    private RecyclerViewHelper recyclerViewHelper;    private int loadCount = 0;
定义了五个变量,分别是 RecyclerView ,String泛型的List,自定义List适配器,本文所提及的Helper,和一个计数器loadCount

我们先看看适配器ListAdapter
public class ListAdapter extends CommonAdapter<String> {    public ListAdapter(@NonNull List<String> dataList) {        super(dataList, R.layout.item_list);    }    @Override    public void convert(BaseViewHolder holder, String s, int position) {    }}
代码很简单,继承了一个CommonAdapter,设定了一个item布局,但需要注意的是这里所继承的CommonAdapter是重写的
我们来看看源码
public abstract class CommonAdapter<T> extends RecyclerView.Adapter<BaseViewHolder>
这是一个抽象类继承于RecyclerView的Adapter
我们来看看整个类的代码
public abstract class CommonAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {    private List<T> dataList;     //T泛型的List    private int itemLayoutId = 0;   //item布局id    public CommonAdapter(@NonNull List<T> dataList, int itemLayoutId) {   //构造方法,这里的NonNull指的是不为null的附加条件        this.dataList = dataList;        this.itemLayoutId = itemLayoutId;    }    @Override    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {   //Holder的onCreate方法,绑定了item布局id        BaseViewHolder holder = new BaseViewHolder(getLayoutView(parent, itemLayoutId));        setListener(holder);        return holder;    }    @Override    public void onBindViewHolder(BaseViewHolder holder, int position) {    //绑定Holder        convert(holder, dataList.get(position), holder.getAdapterPosition());    }    @Override    public int getItemCount() {   //获取item的数目        return dataList.size();    }    public View getLayoutView(ViewGroup parent, int layoutId) {    //返回LayoutView        return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);    }    /**     * 设置     *     * @param viewHolder     */    private void setListener(final BaseViewHolder viewHolder) {           //设置监听,监听点击事件        viewHolder.getConvertView().setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (onItemClickListener != null) {                    int position = viewHolder.getAdapterPosition();  //获取position                    onItemClickListener.onItemClick(v, viewHolder, position);                }            }        });    }    public abstract void convert(BaseViewHolder holder, T t, int position); //抽象的convert方法//点击监听部分源代码    private OnItemClickListener onItemClickListener;      public interface OnItemClickListener {   //监听器接口        void onItemClick(View view, BaseViewHolder holder, int position);    }    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {        this.onItemClickListener = onItemClickListener;    }}
总而言之,CommonAdapter是夹带设置监听点击事件的Adapter,以前的话监听点击是需要我们自己手动添加监听在Adapter中,有了这个之后变得简单了。
需要注意的是这里的BaseViewHolder也是重写的
贴一下代码
public class BaseViewHolder extends RecyclerView.ViewHolder {    private final SparseArray<View> views; //SparseArray,之前的文章有提及,一种效率高的Array,这里使用View泛型    public View convertView;    public BaseViewHolder(View itemView) {        super(itemView);        this.views = new SparseArray<>();        convertView = itemView;    }    public View getConvertView() {        return convertView;    }    public <T extends View> T getView(int viewId) {//返回相应泛型的View        View view = views.get(viewId);        if (view == null) {            view = convertView.findViewById(viewId);            views.put(viewId, view);        }        return (T) view;    }....}
下面给出MainActvity的代码
protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);//设置布局        list_container = (RecyclerView) findViewById(R.id.list_container); //实例化RecyclerView        dataList = new ArrayList<>();            listAdapter = new ListAdapter(dataList);   //设置适配器        //使用helper实现分页加载和加载的Tips        recyclerViewHelper = new RecyclerViewHelper(list_container, listAdapter);        //设置没有数据的Tips        recyclerViewHelper.setTipsEmptyView(R.layout.view_data_empty);        //设置加载中的Tips        recyclerViewHelper.setTipsLoadingView(R.layout.view_data_loading);        //设置加载失败的Tips        recyclerViewHelper.setTipsErrorView(R.layout.view_data_error);        //加载失败,没有数据时Tips的接口        recyclerViewHelper.setTipsListener(new TipsListener() {            @Override            public void retry() {                initData();            }        });        //设置header//        recyclerViewHelper.setHeaderView(R.layout.view_header);        //加载更多的接口        recyclerViewHelper.setLoadMoreListener(new LoadMoreListener() {            @Override            public void loadMore() {                loadNext();            }        });        initData();
    }
给出loadNext和initData方法的代码

    private void loadNext() {        new Thread(new Runnable() {            @Override            public void run() {                try {                    Thread.sleep(800);                } catch (InterruptedException e) {                    e.printStackTrace();                }                runOnUiThread(new Runnable() {                    @Override                    public void run() {                        if (loadCount % 2 != 0) {                            //分页数据加载失败                            recyclerViewHelper.loadMoreError();                        } else if (loadCount < 7) {                            for (int i = 0; i < 10; i++) {                                dataList.add(String.valueOf(i));                            }                            //分页数据加载成功,还有下一页                            recyclerViewHelper.loadMoreFinish(true);                        } else {                            //分页数据加载成功,没有更多。即全部加载完成                            recyclerViewHelper.loadMoreFinish(false);                        }                        loadCount++;                    }                });            }        }).start();    }    private void initData() {        dataList.clear();        new Thread(new Runnable() {            @Override            public void run() {                try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                runOnUiThread(new Runnable() {                    @Override                    public void run() {                        if (loadCount == 0) {                            //首次加载数据成功                            recyclerViewHelper.loadTipsComplete();                        } else if (loadCount == 1) {                            //首次数据记载失败                            recyclerViewHelper.loadTipsError();                        } else {                            for (int i = 0; i < 10; i++) {                                dataList.add(String.valueOf(i));                            }                            recyclerViewHelper.loadTipsComplete();                        }                        loadCount++;                    }                });            }        }).start();    }
到此,已基本实现RecyclerView适配器的加载,可以看出这个Helper可以帮助我们更好的实现Adapter的加载,各种加载提示和分页加载

接下来我们来看看这个Helper的源码
public class RecyclerViewHelper {    private RecyclerView recyclerView;          //RecyclerView    private RecyclerView.LayoutManager layoutManager;    //布局管理器    private RecyclerView.Adapter adapter;    //适配器    private HelperAdapter helperAdapter;      //自定义适配器    private LoadMoreListener loadMoreListener;        //自定义监听器    private boolean hasMore = true;        //是否有更多    private boolean isLoading = false;        //是否正在加载
  //构造方法1    public RecyclerViewHelper(RecyclerView recyclerView, RecyclerView.Adapter adapter) {        this(recyclerView, null, adapter);    }  //构造方法2    public RecyclerViewHelper(@NonNull RecyclerView recyclerView, RecyclerView.LayoutManager layoutManager,                              @NonNull RecyclerView.Adapter adapter) {        this.recyclerView = recyclerView;        this.layoutManager = layoutManager;        this.adapter = adapter;        if (layoutManager == null) {//不传layoutManager默认为LinearLayoutManager            this.layoutManager = new LinearLayoutManager(recyclerView.getContext());        } else {            this.layoutManager = layoutManager;        }        setup();    }    private void setup() {        recyclerView.setLayoutManager(layoutManager);        recyclerView.setHasFixedSize(true);//设置item固定宽高可提高性能        helperAdapter = new HelperAdapter(adapter);        recyclerView.setAdapter(helperAdapter);    //监听RecyclerView的滚动        recyclerView.addOnScrollListener(new RecyclerViewScrollListener() {            @Override            public void loadMore(RecyclerView recyclerView) {                if (isLoading || adapter.getItemCount() == 0)                    return;                if (hasMore) {//设置footer为加载中...                    if (loadMoreListener != null) {                        LoadMoreUtil.updateState(recyclerView, LoadMoreView.State.LOADING, null);                        isLoading = true;                        loadMoreListener.loadMore();                    }                } else {//设置footer为加载完成                    LoadMoreUtil.updateState(recyclerView, LoadMoreView.State.NO_MORE, null);                }            }        });    }    //设置tips为空的view    public RecyclerViewHelper setTipsEmptyView(int layoutId) {        if (helperAdapter != null) {            helperAdapter.setTipsEmptyView(layoutId);        }        return this;    }  //设置正在加载的View    public RecyclerViewHelper setTipsLoadingView(int layoutId) {        if (helperAdapter != null) {            helperAdapter.setTipsLoadingView(layoutId);        }        return this;    }   //设置错误提示的View    public RecyclerViewHelper setTipsErrorView(int layoutId) {        if (helperAdapter != null) {            helperAdapter.setTipsErrorView(layoutId);        }        return this;    }  //设置顶部View    public RecyclerViewHelper setHeaderView(int layoutId) {        if (helperAdapter != null) {            helperAdapter.setHeaderView(layoutId);        }        return this;    }   //加载完成    public void loadTipsComplete() {        if (helperAdapter != null) {            helperAdapter.loadTipsComplete();        }    }    /**     * 加载失败     */    public void loadTipsError() {        if (helperAdapter != null) {            helperAdapter.loadTipsError();        }    }   //加载更多完成    public void loadMoreFinish(boolean hasMore) {        this.hasMore = hasMore;        this.isLoading = false;        if (!hasMore) {            LoadMoreUtil.updateState(recyclerView, LoadMoreView.State.NO_MORE, null);        }        if (helperAdapter != null) {            helperAdapter.notifyDataSetChanged();  //设置改变        }    }    public void loadMoreError() {//设置footer为加载失败        this.hasMore = true;        this.isLoading = false;        LoadMoreUtil.updateState(recyclerView, LoadMoreView.State.ERROR, new View.OnClickListener() {            @Override            public void onClick(View v) {                LoadMoreUtil.updateState(recyclerView, LoadMoreView.State.LOADING, null);                if (loadMoreListener != null) {                    loadMoreListener.loadMore();                }            }        });    }    public void setLoadMoreListener(LoadMoreListener loadMoreListener) {        this.loadMoreListener = loadMoreListener;    }  //设置监听    public void setTipsListener(TipsListener tipsListener) {        if (helperAdapter != null) {            helperAdapter.setTipsListener(tipsListener);        }    }}
可以看出添加了很多提示方面的View
我们来看一看HelperAdapter

public class HelperAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {  //继承于RecyclerView的Adapter泛型是ViewHolder    private static final String TAG = HelperAdapter.class.getSimpleName();  //设置各情况的标志码    public static final int HEADER_VIEW = 0x00000111;    public static final int FOOTER_VIEW = 0x00000222;    public static final int LOADING_VIEW = 0x00000333;    public static final int EMPTY_VIEW = 0x00000444;    public static final int ERROR_VIEW = 0x00000555;    /**     * 第一次加载提示状态     */    public enum Tips {        LOADING, EMPTY, ERROR, NORMAL    }    private Tips tips = Tips.LOADING;   //各类Tips布局ID    private int headerLayoutId = 0;    private int emptyLayoutId = 0;    private int loadingLayoutId = 0;    private int errorLayoutId = 0;  
    //footerView    private View footerView;   //设置适配器    private final RecyclerView.Adapter<RecyclerView.ViewHolder> itemAdapter;    public HelperAdapter(@NonNull RecyclerView.Adapter itemAdapter) {        this.itemAdapter = itemAdapter;    }    /**     * 添加Header     *     * @param headerLayout     */    public void setHeaderView(int headerLayout) {        this.headerLayoutId = headerLayout;    }    /**     * 添加Footer     *     * @param footerView     */    public void setFooterView(View footerView) {        this.footerView = footerView;    }    public View getFooterView() {        return footerView;    }    /**     * 设置空数据显示view     *     * @param emptyLayout     */    public void setTipsEmptyView(int emptyLayout) {        this.emptyLayoutId = emptyLayout;    }    /**     * 设置第一次加载时的view     *     * @param loadingLayout     */    public void setTipsLoadingView(int loadingLayout) {        this.loadingLayoutId = loadingLayout;    }    /**     * 设置第一次加载错误view     *     * @param errorLayout     */    public void setTipsErrorView(int errorLayout) {        this.errorLayoutId = errorLayout;    }    /**     * 加载完成     */    public void loadTipsComplete() {        if (itemAdapter.getItemCount() > 0) {            tips = Tips.NORMAL;        } else {            tips = Tips.EMPTY;        }        notifyDataSetChanged();    }    /**     * 加载失败     */    public void loadTipsError() {        if (itemAdapter.getItemCount() == 0) {            tips = Tips.ERROR;        }        notifyDataSetChanged();    }    /**     * 第一次加载重试     */    public void loadTipsRetry() {        if (itemAdapter.getItemCount() == 0) {            tips = Tips.LOADING;        }        notifyDataSetChanged();    }    private int getHeaderViewCount() {        return getViewCount(headerLayoutId);    }    private int getFooterViewCount() {        return footerView == null ? 0 : 1;    }    private int getEmptyViewCount() {        return getViewCount(emptyLayoutId);    }    private int getLoadingViewCount() {        return getViewCount(loadingLayoutId);    }    private int getErrorViewCount() {        return getViewCount(errorLayoutId);    }    private int getViewCount(int layoutId) {        return layoutId > 0 ? 1 : 0;    }    public View getLayoutView(ViewGroup parent, int layoutId) {        return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);    }    /**     * 没有数据的view显示逻辑     *     * @return     */    public int getEmptyViewType() {        if (tips == Tips.LOADING && getLoadingViewCount() > 0) {            return LOADING_VIEW;        } else if (tips == Tips.ERROR && getErrorViewCount() > 0) {            return ERROR_VIEW;        } else {            return EMPTY_VIEW;        }    }    /**     * 获取显示类型     *     * @param position     * @return     */    @Override    public int getItemViewType(int position) {        if (getHeaderViewCount() == 0) {            if (itemAdapter.getItemCount() == 0 && getEmptyViewCount() > 0) {                return getEmptyViewType();            }        } else {            if (position == 0) {                return HEADER_VIEW;            } else if (position == 1 && itemAdapter.getItemCount() == 0 && getEmptyViewCount() > 0) {                return getEmptyViewType();            }        }        if (position >= (getHeaderViewCount() + itemAdapter.getItemCount())) {            return FOOTER_VIEW;        }        return super.getItemViewType(position - getHeaderViewCount());    }    /**     * 加载holder显示布局     *     * @param parent     * @param viewType     * @return     */    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        if (viewType == LOADING_VIEW) {            return new BaseViewHolder(getLayoutView(parent, loadingLayoutId));        } else if (viewType == ERROR_VIEW) {            BaseViewHolder holder = new BaseViewHolder(getLayoutView(parent, errorLayoutId));            if (tipsListener != null) {                holder.getConvertView().setOnClickListener(new View.OnClickListener() {                    @Override                    public void onClick(View v) {                        loadTipsRetry();                        tipsListener.retry();                    }                });            }            return holder;        } else if (viewType == EMPTY_VIEW) {            BaseViewHolder holder = new BaseViewHolder(getLayoutView(parent, emptyLayoutId));            if (tipsListener != null) {                holder.getConvertView().setOnClickListener(new View.OnClickListener() {                    @Override                    public void onClick(View v) {                        loadTipsRetry();                        tipsListener.retry();                    }                });            }            return holder;        } else if (viewType == HEADER_VIEW) {            return new BaseViewHolder(getLayoutView(parent, headerLayoutId));        } else if (viewType == FOOTER_VIEW) {            return new BaseViewHolder(footerView);        } else {            return itemAdapter.onCreateViewHolder(parent, viewType);        }    }    /**     * 将数据绑定到布局上     *     * @param holder     * @param position     */    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        int headerCount = getHeaderViewCount();        if (itemAdapter.getItemCount() > 0 && position >= headerCount && position < headerCount + itemAdapter.getItemCount()) {            itemAdapter.onBindViewHolder(holder, position - headerCount);        } else {            ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();            if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {                ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);            }        }    }    @Override    public int getItemCount() {        if (itemAdapter.getItemCount() == 0) {//没有数据,只显示header+emptyView            return getHeaderViewCount() + getEmptyViewCount();        } else {//有数据不显示emptyView            return getHeaderViewCount() + getFooterViewCount() + itemAdapter.getItemCount();        }    }    private TipsListener tipsListener;    public void setTipsListener(TipsListener tipsListener) {        this.tipsListener = tipsListener;    }}

各部分监听器就不一一列出了,通过对源码的剖析,可以看出Helper实际上改添了许多关于Tips的状态View
同时也简化了Adapter中的item点击事件监听,使我们可以更好地去处理点击事件,关于RecyclerViewHelper就到这里了.
0 0