Android 一起来封装一个 RecyclerViewAdapter
2016-08-31 16:41
537 查看
前言
上一篇我们一起封装了一个还算简单实用的 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-多列表的项目(Rxjava+Rtrofit+Recyclerview+Glide+Adapter封装)之(二)网络层的封装
- Android中对RecyclerView Adapter封装解析
- Android RecyclerView封装RecyclerAdapter及解决与ScrollView冲突
- Android RecyclerView Adapter及Holder的封装【原创】
- Android-多列表的项目(Rxjava+Rtrofit+Recyclerview+Glide+Adapter封装)之(一)项目架构
- Android - 是时候为自己封装一个BaseRecyclerAdapter了
- Android开发之ButterKnife,GreenDao简单运用,以及推荐并使用一个好用的开源库BaseRecyclerViewAdapterHelper。
- Android 对ListView和RecyclerView的两个BaseAdapter封装分享
- Android 封装RecyclerView的Adapter
- android简洁代码封装 -- RecyclerView.Adapter之MultiTypeAdapter封装
- RecyclerView Adapter 优雅封装,一个Adapter搞定所有列表
- Android-多列表的项目(Rxjava+Rtrofit+Recyclerview+Glide+Adapter封装)之(二)网络层的封装
- Android进阶学习-打造一个通用的RecyclerViewAdapter
- Android RecyclerView(五)封装Holder与Adapter(Android 5.0 新特性)
- 一个很好的RecyclerView的Adapter封装
- Android 对封装RecyclerView.Adapter讲解
- Android-多列表的项目(Rxjava+Rtrofit+Recyclerview+Glide+Adapter封装)之(一)项目架构
- Android 封装RecyclerView.Adapter,省其ViewHolder
- Android 一起来封装一个简单易用的Adapter
- 安卓学习笔记---android RecyclerView一个通用的BaseAdapter