先介绍下为什么这么做,因为RecyclerView需要一个javabean,同时呢,对于整个系统中的一个对象,也需要建造一个javabean。但是很明显,RecyclerView中的那个bean显然是整个系统中那个对象javabean的子集。所以我觉得不应该专门为RecyclerView设置一个bean,你想要给他什么数据,多传几个集合不就好了?为什么一定要并在一个集合里?所以我认为,javabean反而是最容易忽视,也是最高的耦合度的体现。
本来的List---List<XxxxBean>
现在的List---List<String> List<Bitmap> List<...>
(我觉得下面那种才是健康,更容易维护的形式!!!用户要改需求,增加一个List就可以和一行绑定的代码就可以!!!)
先看一下我的除了通用的ViewHolder和通用的Adapter之外的所有代码
CommonAdapter adapter = new CommonAdapter<String, Bitmap, String, String, String>(this,R.layout.item, stringList, bitmapList, null, null, null) { @Override protected void convert(CommonViewHolder holder, int position, String s, Bitmap bitmap, String s2, String s3, String s4) { ((TextView)((ViewGroup)holder.getItemView()).getChildAt(0)).setText(s); ((ImageView)((ViewGroup)holder.getItemView()).getChildAt(1)).setImageBitmap(bitmap); } }; mRv.setAdapter(adapter); mRv.setLayoutManager(new LinearLayoutManager(this));
这里我就使用了两个数据类型,一个String,一个是Bitmap,后面的泛型不得不指定,就瞎指定了几个(也可以像rxjava写9个类,这样就可以动态指定泛型个数了)。整个流程下来,就是舒服二字!
假如说这是一个聊天系统,用户一开始说,他要的是String类型的,因为只发文本就可以了 。但是他心思变的很快,说,我想要一个通用的消息类型,比如是MyMessage类型,所以这个时候,你得到bean里去改,得到adapter里去改,如果你的业务已经做了很多了,大部分的业务都要改!这里就可以规避一下。只需要List<String>变成List<MyMessage>就可以了,舒服。
看一下抽象出来的通用的ViewHolder和Adapter,思路很简单,一看就懂:
ViewHolder
public class CommonViewHolder extends RecyclerView.ViewHolder { private View itemView = null; private SparseArray<View> mViewSparseArray;//类似map,内部结构还没来得及看 public CommonViewHolder(View itemView) { super(itemView); mViewSparseArray = new SparseArray<>(); this.itemView = itemView; } public View holdAndGetView(int viewId) { View v = mViewSparseArray.get(viewId); if (v == null) { v = itemView.findViewById(viewId); } return v; } public View getItemView() { return itemView; } }其实我的这个holdAndGetView方法都没用到,我的item布局也没设置id,直接通过getChildAt的形式去取了,很舒服。(如果客官狠一点,完全可以改造一下,让item布局都不要了,直接new个常用的根布局出来,然后设置布局参数往里面加子控件就可以。)
CommonAdapter
public abstract class CommonAdapter<A, B, C, D, E> extends RecyclerView.Adapter<CommonViewHolder> { private Context context = null; private LayoutInflater inflater = null; private int layoutId = 0; private List<A> aList = null; private List<B> bList = null; private List<C> cList = null; private List<D> dList = null; private List<E> eList = null; // TODO: 2017/12/31 POJO类其实就是一种耦合 改动起来 非常非常非常不方便 //make sure list size is equals public CommonAdapter(Context context, int layoutId, List<A> aList, List<B> bList, List<C> cList, List<D> dList, List<E> eList) { this.context = context; this.inflater = LayoutInflater.from(context); this.layoutId = layoutId; this.aList = aList != null ? aList : null; this.bList = bList != null ? bList : null; this.cList = cList != null ? cList : null; this.dList = dList != null ? dList : null; this.eList = eList != null ? eList : null; } // TODO: 2017/12/31 先只搞单item type的 @Override public CommonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = inflater.inflate(layoutId, parent, false); return new CommonViewHolder(v); } @Override public void onBindViewHolder(CommonViewHolder holder, int position) { A a = aList != null ? aList.get(position) : null; B b = bList != null ? bList.get(position) : null; C c = cList != null ? cList.get(position) : null; D d = dList != null ? dList.get(position) : null; E e = eList != null ? eList.get(position) : null; convert(holder, position, a, b, c, d, e); } protected abstract void convert(CommonViewHolder holder, int position, A a, B b, C c, D d, E e); @Override public int getItemCount() { return aList.size(); } }
最后讲一下,每个安卓开发者,都不应该使用别人封装的RecyclerView,而是应该有自己的一RrecyclerView,你想扩充功能的时候,你是改不了别人的gradle的。只有自己的,改起来才最方便,每个人对于RecyclerView的业务需求都是不一样的(不仅仅是list,还有下拉刷新等等各式各样花里胡哨的操作)。有了专门适合自己的一套,其开发效率和可维护重用性,可以说是正常人的数倍,而且就算出了错,自己也非常容易盘查。
github地址:(接下来还会添加多item布局等功能)https://github.com/xubinhong/MyRecyclerView4