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

来源:互联网 发布:淘宝违规记录多久清除 编辑:程序博客网 时间:2024/06/03 06:38

入行几个月了,一直想自己封装一些类,刚好遇到了这个问题,现在跟大家分享。
注意点
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上看看,一起交流学习