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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zw21544182/article/details/78674378

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

猜你喜欢

转载自blog.csdn.net/zw21544182/article/details/78674378