(再次更新)打造RecyclerView万能适配器,上拉刷新,下拉加载

入行几个月了,一直想自己封装一些类,刚好遇到了这个问题,现在跟大家分享。
注意点
1 泛型擦除
2 需要防止类型转换异常
github地址:https://github.com/zw21544182/MyBaseDemo
(里面还有部分FileUtils常用相关方法),欢迎start 一起交流进步
关于RecyclerView.Adapter 一般的套路是这个样子的

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //创建ViewHolder
        return null;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
    //绑定数据
    }

    @Override
    public int getItemCount() {
        //获取数据行数
        return 0;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View itemView) {
            //绑定Itme 中的View
            super(itemView);
        }
    }
}

现在我想写一个Adapter的基类
最初的想法是指定一个泛型,像这样

public class MyRecyclerViewAdapter<T> extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
    List<T> data;
    Context context;
    int layoutId;

    public MyRecyclerViewAdapter(List<T> data, Context context, int layoutId) {
        this.data = new ArrayList<>();
        data.addAll(data);
        this.context = context;
        this.layoutId = layoutId;
    }

    //添加一些 setData clearData等方法
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //创建ViewHolder
        View view = LayoutInflater.from(this.context).inflate(this.layoutId, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        //绑定数据
    }

    @Override
    public int getItemCount() {
        //获取数据行数
        return data.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View itemView) {
            //绑定Itme 中的View
            super(itemView);
        }
    }
}

自我感觉这样很完美,但是编译通不过。报没有实现子类onBindViewHolder的错,额,好吧。就这样,尴尬了一会,在网上查了查资料。后来想到为什么不直接泛型擦除呢?
最后就有了现在这个BaseRecyclerAdapter

/**
 * 创建时间: 2017/11/29
 * 创建人: Administrator
 * 功能描述:RecyclerView基类(需要注意类型转换问题)
 */
public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter<BaseRecyclerViewAdapter.BaseViewHolder> {
    protected ArrayList data;
    protected Context context;
    protected List<Integer> layoutIds;//布局集合
    protected boolean isMore = true;//上拉刷新时,是否有更多数据

    public BaseRecyclerViewAdapter(List data, Context context, List<Integer> layoutIds) {
        this.data = new ArrayList<>();
        this.layoutIds = new ArrayList<>();
        this.data.addAll(data);
        this.layoutIds.addAll(layoutIds);
        this.context = context;
    }

    public void setData(List data) {
        this.data.clear();
        this.data.addAll(data);
        notifyDataSetChanged();
    }

    public void clearAll() {
        this.data.clear();
        notifyDataSetChanged();
    }

    public Object getDataByPos(int index) {
        if (data.size() <= index) {
            return null;
        }
        return data.get(index);
    }

    public void addData(Object t) {
        data.add(t);
        notifyDataSetChanged();
    }

    public void addDatas(List data) {
        this.data.addAll(data);
        notifyDataSetChanged();
    }
#重要 设置viewType
    @Override
    public int getItemViewType(int position) {
        if (position + 1 == getItemCount()) {
            return -1;//最后行时设为-1显示footLayout
        } else {
            return position;//其他设为位置
        }

    }

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int pos) {
        if (data.size() == 0) {//当data数据为0时
            View view = LayoutInflater.from(context).inflate(R.layout.zwbase_no_data, parent, false);
            //显示暂无数据布局
            return new BaseViewHolder(view);
        }
        if (pos == -1) {//pos为-1表示最后一行 
            View view = LayoutInflater.from(context).inflate(R.layout.zwbase_footlayout, parent, false);
            //显示底部布局
            return new FootViewHolder(view);
        }
        int layout = getLayoutIdByPos(pos);
        View view = LayoutInflater.from(context).inflate(layout, parent, false);
        BaseViewHolder baseViewHolder = new BaseViewHolder(view);
        clickView(baseViewHolder, data.get(pos), pos);
        return baseViewHolder;
    }

    protected int getLayoutIdByPos(int pos) {
        int res = 0;
        if (pos < layoutIds.size()) {//layoutIds是存放布局的集合
            res = layoutIds.get(pos);
        } else {
            res = layoutIds.get(pos % layoutIds.size());
        }
        return res;
    }


    /**
     * 在oncreateViewHolder方法中设置点击事件
     * 避免重复调用
     * @param baseViewHolder itme控件
     * @param o              itme    实体类
     * @param pos            位置
     */
    protected abstract void clickView(BaseViewHolder baseViewHolder, Object o, int pos);

    protected abstract void setItmeData(BaseViewHolder baseViewHolder, Object itmeModule, int position) throws ClassCastException;

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        if (data.size() == 0) {
            ImageView nodataImage = (ImageView) holder.getViewById(R.id.zwbase_imageview);
            TextView nodataText = (TextView) holder.getViewById(R.id.zwbase_tvNoData);
            setNodataInfo(nodataImage, nodataText);
            return;
        }
        if (holder instanceof FootViewHolder) {
            //判断为底部布局时
            if (isMore) {//再次判断是否还有更多数据,加载相应的布局
                holder.getViewById(R.id.loadmore).setVisibility(View.VISIBLE);
                holder.getViewById(R.id.nodata).setVisibility(View.GONE);
            } else {
                holder.getViewById(R.id.loadmore).setVisibility(View.GONE);
                holder.getViewById(R.id.nodata).setVisibility(View.VISIBLE);
            }
            return;
        }
        try {
            setItmeData(holder, data.get(position), position);//设置显示数据
        } catch (ClassCastException e) {
            e.printStackTrace();
        }
    }

    protected void setNodataInfo(ImageView nodataImage, TextView nodataText) {
    }


    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size() + 1;//数据为0或为空时返回0,否则data.size()+1
    }

    public void setMore(boolean more) {
        //暴露方法给Activity
        this.isMore = more;
    }

    protected class FootViewHolder extends BaseViewHolder {
        public FootViewHolder(View itemView) {
            super(itemView);
        }
    }

    public class BaseViewHolder extends RecyclerView.ViewHolder {
        //该类下部分方法可以自行添加
        View rootView;

        public BaseViewHolder(View itemView) {
            super(itemView);
            rootView = itemView;
        }

        public void setText(int viewId, int resourceId) {
            ((TextView) getViewById(viewId)).setText(resourceId);
        }

        public void setClickListent(int viewId, View.OnClickListener onClickListener) {
            getViewById(viewId).setOnClickListener(onClickListener);
        }

        public void setText(int viewId, String content) {
            ((TextView) getViewById(viewId)).setText(content);
        }

        public void setCheckChangeListen(int viewId, CompoundButton.OnCheckedChangeListener onCheckedChangeListener) {
            ((CheckBox) getViewById(viewId)).setOnCheckedChangeListener(onCheckedChangeListener);
        }

        public void setImageSource(int imageViewId, int sourceId) {
            ImageView imageView = (ImageView) getViewById(imageViewId);
            imageView.setImageResource(sourceId);
        }

        public View getViewById(int viewId) {
            return rootView.findViewById(viewId);
        }
    }
}

在打造我们自己的适配器时,我们可以继承BaseRecyclerViewAdaPter

public class MyAdapter extends BaseRecyclerViewAdapter {

    public MyAdapter(List data, Context context, List<Integer> layoutIds) {
        super(data, context, layoutIds);
    }

    @Override
    protected void clickView(BaseViewHolder baseViewHolder, Object o, int pos) {

    }

    @Override
    protected void setItmeData(BaseViewHolder baseViewHolder, Object itmeModule, int position) throws ClassCastException {
        int layoutNum = (position % layoutIds.size());

        switch (layoutNum) {
            case 0:
                baseViewHolder.setText(R.id.tvText, (String) itmeModule);
                break;
            case 1:
                baseViewHolder.setImageSource(R.id.ivImage, R.mipmap.image);
                break;
        }
    }
}

在activity中传入相关的布局Id号即可

  data = new ArrayList<>();
        layoutIds = new ArrayList<>();
        layoutIds.add(R.layout.layout_rvitme);
        layoutIds.add(R.layout.layout_image);
//需要注意的是layoutIds传入的布局Id的顺序和个数要与Adapter中的setItmeData对应
        for (int i = 0; i < 100; i++) {
            data.add("sssss " + i);
        }
        baseRecyclerViewAdapter = new MyAdapter(data, this, layoutIds);
        myRview.setLayoutManager(new LinearLayoutManager(this));
        myRview.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        myRview.setAdapter(baseRecyclerViewAdapter);

最后, 花了一些时间,封装成了可刷新的view 下拉刷新用的官方+接口回调,上拉加载也是 可以去github上看看,一起交流学习

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容