Android 一起来封装一个 RecyclerViewAdapter

原创 2016年08月31日 16:41:56

前言

上一篇我们一起封装了一个还算简单实用的 Adapter,可惜是 ListView、GridView 用的。在 RecyclerView 大行其道的如今,对应 Adapter 的使用简单也是一个必然的需求。

正文

按照惯例,先来看看一个原始的 RecyclerViewAdapter 是怎么写的

RecyclerView.Adapter adapter = new RecyclerView.Adapter() {
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                View itemView = LayoutInflater.from(context).inflate(layoutId, parent, false);
                return new Holder(itemView);
            }

            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
                Holder holder = (Holder) viewHolder;

                holder.textView.setText(dataSource.get(position));
                holder.button.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //TODO
                    }
                });
            }

            @Override
            public int getItemCount() {
                return dataSource.size();
            }
        };
private class Holder extends RecyclerView.ViewHolder {

        public TextView textView;
        public Button button;

        public Holder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(textViewId);
            button = itemView.findViewById(buttonId);
        }
    }

以上代码纯属盲打,如有错误敬请谅解。

大致上我们能看到,相对于 ListView,RecyclerView 帮我们实现了 Item 的复用逻辑,不需要我们再写,但还是每次都要写一个 ViewHolder 类。之前我们是调用一个自己写的静态 ViewHolder 类,但是 RecyclerView 需要的 ViewHolder 一定是 RecyclerView.ViewHolder 或其子类,所以我们只能继承 RecyclerView.ViewHolder 来做封装工作。

public class RecyclerViewHolder extends RecyclerView.ViewHolder {

    public RecyclerViewHolder(View itemView) {
        super(itemView);
    }

    public <T extends View> T getChildView(int id) {
        return (T) itemView.findViewById(id);
    }
}

其实只是添加了一个 getChildView 的方法用来获取子 View 而已。

Adapter 的封装也很简单,只是添加了一个绑定数据的抽象方法:

public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerViewHolder> {

    /**
     * 由子类实现绑定方法
     * @param holder
     * @param data
     * @param position
     */
    protected abstract void onBindData(RecyclerViewHolder holder, T data, int position);

    protected Context mContext;
    protected List<T> mData;
    protected LayoutInflater mInflater;
    protected int layoutRes;

    public RecyclerAdapter(Context context, List<T> data, int layoutRes) {
        this.mData = data;
        this.mContext = context;
        this.layoutRes = layoutRes;
        this.mInflater = LayoutInflater.from(mContext);
    }

    public void refresh(List<T> data) {
        try {
            this.mData = data;
            notifyDataSetChanged();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new RecyclerViewHolder(mInflater.inflate(layoutRes, parent, false));
    }

    @Override
    public void onBindViewHolder(RecyclerViewHolder holder, int position) {
        onBindData(holder, mData.get(position), position);
    }

    @Override
    public int getItemCount() {
        return mData.size();
    }
}

我们来看看现在使用起来方不方便?

RecyclerAdapter adapter = new RecyclerAdapter<String>(this, dataSource, layoutRes) {
            @Override
            protected void onBindData(RecyclerViewHolder holder, String data, int position) {
                TextView textView = holder.getChildView(textViewId);
                Button button = holder.getChildView(buttonId);

                textView.setText(data);
                button.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //TODO
                    }
                });
            }
        };

有木有一种很亲切的感觉?终于又回到了一个方法实现 Adapter 的日子了 T_T ~~

小结

封装之后才发现,其实 RecyclerView 的 Adapter 是可以封装得比 ListView 更为简洁易用的,这应该归功于 RecyclerView 自身就实现了缓存复用。

真·正文

还记得上一篇文章我就说过这还不是极简吗?仔细看上面的代码,每次重写绑定方法的时候,几乎都要先用 holder 的 getChild 方法获取到 view 实例,再进行填充数据、添加监听等操作。有没有一种办法能一步到位呢?

当然有!

先看代码

public class RecyclerViewHolder extends RecyclerView.ViewHolder {

    public RecyclerViewHolder(View itemView) {
        super(itemView);
    }

    public <T extends View> T getChildView(int id) {
        return (T) itemView.findViewById(id);
    }

    public RecyclerViewHolder setText(int viewId, CharSequence charSequence) {
        TextView textView = getChildView(viewId);
        textView.setText(charSequence);
        return this;
    }
    ......
}

可以看出,我们给 ViewHolder 添加了 setText 方法,传入了 viewId 和我们想要设置的值,在方法内部去 getChildView 并进行了数据填充。同样的,设置监听等方法也可以这样子去实现。

RecyclerAdapter adapter = new RecyclerAdapter<String>(this, dataSource, layoutRes) {
            @Override
            protected void onBindData(RecyclerViewHolder holder, String data, int position) {
                holder.setText(textViewId, data)
                        .setOnClickListener(buttonId, new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                //TODO
                            }
                        });
            }
        };

再安利一下 lambda 表达式

RecyclerAdapter adapter = new RecyclerAdapter<String>(this, dataSource, layoutRes) {
            @Override
            protected void onBindData(RecyclerViewHolder holder, String data, int position) {
                holder.setText(textViewId, data)
                        .setOnClickListener(buttonId, (v) -> {/** TODO */});
            }
        };

是不是感觉棒棒哒?很多常用的方法都可以放到 ViewHolder 中去,比如 setTextSize、setTextColor、setVisibility、setImageResource、setBackgroundColor 等。

因为篇幅的关系,原本计划一起写的 ItemType 处理很难再塞进来。再加上 databinding 模式下的 Adapter 封装,感觉 Adapter 这个系列就够我写好一阵了,会不会有点狗血?

感谢

鸿扬大神:https://github.com/hongyangAndroid/baseAdapter
以及我自己的开源项目:https://github.com/neverwoodsS/zy-open

Android 一起来封装一个简单易用的Adapter

还记得我初学 Android 没多久又需要用到 ListView 的时候还不会写 Adapter,结果我居然硬生生的用 TableLayout 和 LinearLayout 把 ListView 给替...

RecyclerViewAdapter封装(上)

做什么玩意儿都是从需求开始做,要封装RecyclerViewAdapter,首先我们就得明白为什么要封装它,,不过这好像都是废话,肯定是为了更好用。。。but,要不是在实际需求中一步步遇到各种问题,是...

Android 可分组的RecyclerViewAdapter

转载请说明出处:http://blog.csdn.net/u010177022/article/details/65448231 今天给大家介绍的是一个可以实现数据分组显示的RecyclerView...

封装RecyclerViewAdapter实现RecyclerView下拉刷新上拉加载更多

实现关于下拉刷新使用的是github上的项目Ultra Pull To Refresh项目。 gradle依赖如下: compile 'in.srain.cube:ultra-ptr:1.0.11...

Android开发中如何把多个JSONArray组合(拼接)在一起,组成一个整体的字符串。

JSONArray数组的组合拼接: 有几个就在里面写几个参数。 方法代码: public String joinJSONArry(JSONArray jsonArray1, JSONArray j...

(Android自定义View)来来来,一起再撸一个Material风格loadingView。

很久很久以前,撸了一款loadingview(点击这里回顾),当时觉得还不错,现在看看觉得好丑啊!!! 于是想再撸一个,无意间在这里看到一个很不错的效果,于是手痒了,就想动动手,算起来,也有很久没有写...

一起Talk Android吧(第九回:Java中的封装:一)

各位看官们,大家好,上一回中咱们说的是Java中面向对象的例子,这一回咱们说的例子是Java中的封装。闲话休提, 言归正转。让我们一起Talk Android吧!...
  • talk_8
  • talk_8
  • 2017年03月05日 09:43
  • 402

[Python]一起来写一个Python爬虫工具类whyspider

写了很多简单的Python爬虫的小例子,今天突然想做个开源的工具包,在gitcafe上和大家一起分享源码。项目源地址:https://gitcafe.com/callmewhy/whyspider今天...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android 一起来封装一个 RecyclerViewAdapter
举报原因:
原因补充:

(最多只允许输入30个字)