高扩展性的RecyclerView通用Adapter

RecyclerView 可以说是 Android 开发最常用到的控件之一了,每一次用到都 new 一个专门的 Adapter 不仅效率低,而且也没有必要,因为大部分的 Adapter 功能都是类似的。那么就来封装一个通用的、易用的、高扩展性 Adapter 吧。

先看效果图:

same_type.png
different_type.png

以上就是最常见的显示单独 viewType 种类和任意多个 viewType 种类列表项的列表。并且最常用的列表项的点击事件也已经方便的提供复写方法,具体的使用方法如下:

引入

compile 'com.yinzihao:YinAdapter:{latest-version}'

使用指南

BaseAdapter

适用于只有一种 ItemViewType 的列表。其中泛型 T 表示数据源的类型。

    BaseAdapter baseAdapter = new BaseAdapter(this, personBeanList, R.layout.item_male){
            @Override
            public void onDataBind(CommonViewHolder viewHolder, PersonBean data, int position) {
                //绑定数据
                viewHolder.getTextView(R.id.tv_name).setText(data.getName());
            }

            @Override
            public void onItemClick(CommonViewHolder commonViewHolder, View view, int position) {
                //整个列表项的点击事件
                Toast.makeText(context, "onItemClick position = " + position, Toast.LENGTH_SHORT).show();
            }

            @Override
            public boolean onItemLongClick(CommonViewHolder commonViewHolder, View view, int position) {
                //整个列表项的长按事件
                Toast.makeText(context, "onItemLongClick position = " + position, Toast.LENGTH_SHORT).show();
                return false;
            }
        }

在构造函数中传入数据源和列表项的布局文件,在onDataBind中绑定数据源内容到布局中既可完成显示。

CommonAdapter

适用于有超过一种 ItemViewType 的列表(例如聊天列表分我的和对方的)。

CommonAdapter commonAdapter = new CommonAdapter(context, personBeanList) {
    @Override
    public List> getDataTypes() {
        DataType maleDateType = new DataType() {
            @Override
            public int getLayoutId() {
                return R.layout.item_male;
            }

            @Override
            public boolean isMatching(PersonBean data, int position) {
                return data.getSex() == 1;
            }

            @Override
            public void dataBind(CommonViewHolder viewHolder, PersonBean data, int position) {
                viewHolder.getTextView(R.id.tv_name).setText(data.getName());
                viewHolder.getView(R.id.tv_sex).setText("男");
            }

            @Override
            public void onItemClick(CommonViewHolder commonViewHolder, View view, int position) {
                Toast.makeText(context, "onItemClick position = " + position, Toast.LENGTH_SHORT).show();
            }

            @Override
            public boolean onItemLongClick(CommonViewHolder commonViewHolder, View view, int position) {
                Toast.makeText(context, "onItemLongClick position = " + position, Toast.LENGTH_SHORT).show();
                return false;
            }
        };

        DataType femaleDateType = new DataType() {
            @Override
            public int getLayoutId() {
                return R.layout.item_female;
            }

            @Override
            public boolean isMatching(PersonBean data, int position) {
                return data.getSex() == 0;
            }

            @Override
            public void dataBind(CommonViewHolder viewHolder, PersonBean data, int position) {
                viewHolder.getTextView(R.id.tv_name).setText(data.getName());
                viewHolder.getView(R.id.tv_sex).setText("女");
            }

            @Override
            public void onItemClick(CommonViewHolder commonViewHolder, View view, int position) {
                Toast.makeText(context, "onItemClick position = " + position, Toast.LENGTH_SHORT).show();
            }

            @Override
            public boolean onItemLongClick(CommonViewHolder commonViewHolder, View view, int position) {
                Toast.makeText(context, "onItemLongClick position = " + position, Toast.LENGTH_SHORT).show();
                return false;
            }
        };
        List> list = new ArrayList<>();
        list.add(maleDateType);
        list.add(femaleDateType);
        return list;
    }

    @Nullable
    @Override
    public DataTypeForTheRest getDefaultDataTypesForRest() {
        return new DataTypeForTheRest() {
            @Override
            public int getLayoutRes() {
                return R.layout.item_the_rest;
            }

            @Override
            public void dataBind(CommonViewHolder viewHolder, PersonBean data, int position) {
                viewHolder.getTextView(R.id.tv_name).setText(data.getName());
                viewHolder.getView(R.id.tv_sex).setText("特别");
            }

            @Override
            public void onItemClick(CommonViewHolder commonViewHolder, View view, PersonBean data, int position) {

            }

            @Override
            public boolean onItemLongClick(CommonViewHolder commonViewHolder, View view, PersonBean data, int position) {
                return false;
            }
        };
    }
    };

CommonAdapter 需要你自己在 getDataTypes() 抽象方法中列出你需要区分显示和处理的 DataType ,然后拼装成列表返回。
注意每个 DataType 中的 isMatching() 方法需要判断数据源是否应该属于当前的 DataType,并且注意唯一性,如果一个数据即匹配一种 DataType 又匹配了另一种 DataType,则会抛出异常。
getDefaultDataTypesForRest() 方法中可以返回一个 DataTypeForTheRest 对象,当数据源不匹配 getDataTypes() 中的任何类型时,会匹配上此对象,你可以统一处理它们的显示。

LoadMoreWrapperAdapter

当需要上拉列表加载更多功能时,只需要使用装饰者模式在原来的 adapter 上装饰 LoadMoreWrapperAdapter 作为新的 adapter 既可。

LoadMoreWrapperAdapter loadMoreWrapperAdapter = new LoadMoreWrapperAdapter<>(adapter);

如果需要自定义加载更多栏的布局样式,则使用:

LoadMoreWrapperAdapter loadMoreWrapperAdapter = new LoadMoreWrapperAdapter<>(adapter, R.layout.load_more_layout);

recyclerViewaddOnScrollListener() 中设置 LoadMoreWrapperAdapter.OnLoadMoreListener 实现加载更多事件的回调

    recyclerView.addOnScrollListener(new LoadMoreWrapperAdapter.OnLoadMoreListener() {
        @Override
        public void onRefresh() {
            if (personBeanList.size() > 22 * 10) {
                loadMoreWrapperAdapter.noMoreToLoad();
                return;
            }
            List init = PersonBean.init();
            personBeanList.addAll(init);
            loadMoreWrapperAdapter.loadFinish();
            loadMoreWrapperAdapter.notifyDataSetChanged();
        }
    });

注意,当本次加载结束时需要手动调用 loadMoreWrapperAdapterloadFinish() 方法。当没有更多数据时需要手动调用 loadMoreWrapperAdapternoMoreToLoad() 方法。

你可能感兴趣的:(高扩展性的RecyclerView通用Adapter)