虽然很多新项目都在使用RecyclerView,但是很多开发者在某些场景下还是倾向于使用ListView或者GridView,然后需要写很多Adapter。有一次项目组开始一个新项目的时候,同事带来了一个网上说的***Adapter。在使用的时候,他发现即使是单视图类型的逻辑判断很复杂也很不方便,更何况是在适配器Adapter中使用多视图类型。这只是个人看法,未必能把握到本质。当然随着RecyclerView的使用,网上也有很多关于封装RecyclerView多视图Adapter的博客。MultiType3.0是大神写的比较全面的Adapter。***Adapter本身使用不是很方便,参考RecyclerView。Adapter的实现只是简单的封装了BaseAdapter。封装的目的一是减少代码编写,二是让逻辑看起来更清晰。我们知道,在RecyclerView的Adapter实现中,将View的创建和数据绑定分开,同时将View的查找和创建分开。本文主要介绍如何将BaseAdapter的使用封装为RecyclerView的Adapter的使用。一致。由于我们在Adapters中经常使用简单的视图类型,即单视图类型,本文将单视图类型的Adapters单独封装,使用比多视图类型的Adapter更严格的数据类型检查。同时,使用起来也很方便。RecyclerView中Adapter的使用在使用RecyclerView的Adapter时,我们首先需要继承一个RecyclerView的静态内部类Adapter,然后重写三个方法。其实下面三个方法都要重写,因为都是抽象方法。getItemCount()onBindViewHolder(VHholder,intposition)onCreateViewHolder(ViewGroupparent,intviewType)一般重写上面三个方法就可以了,但是如果有多个视图类型,在第三个方法onCreateViewHolder()方法中我们也有你可以看到有一个参数viewType,用于为不同的viewType创建不同的ViewHolder,所以需要重写一个方法getItemViewType(intposition),这个方法很像BaseAdapter针对多种视图类型的实现方法,在BaseAdapter另外需要重写一个方法getViewTypeCount(),但是在RecyclerView的Adapter中不需要这个方法。简单类型AdapterprivateclassMyAdapterextendsRecyclerView.Adapter{@OverridepublicintgetItemCount(){returnCOUNT;}@OverridepublicvoidonBindViewHolder(MyViewHolderholder,intposition){holder.textView.setText("TEXT_"+position);}@OverridepublicMyViewHolderonCreateViewLayouttype=flatViewer(ViewGroupparent).from(getApplicationContext()).inflate(R.layout.item_text,parent,false);MyViewHolderholder=newMyViewHolder(view);returnholder;}}privatestaticclassMyViewHolderextendsRecyclerView.ViewHolder{privateTextViewtextView;publicMyViewHolder(ViewitemView){super(itemView);textView=(TextView)itemView.findViewById(R.id.textView);}}复合类型AdapterprivateclassMyAdapterextendsRecyclerView.Adapter{@OverridepublicintgetItemCount(){returnCOUNT;}@OverridepublicintgetItemViewType(intposition){returnposition%2==0?TYPE_IMAGE:TYPE_TEXT;}@OverridepublicvoidonBindViewHolder(ViewHolderholder,intposition){inttype=getItemViewType(位置);开关(类型){caseTYPE_TEXT:((MyTextHolder)holder).textView.setText("TEXT_"+position);break;caseTYPE_IMAGE:((MyImageHolder)holder).imageView.setImageResource(R.drawable.image);break;}}@OverridepublicViewHolderonCreateViewHolder(ViewGroupparent,intviewType){Viewview;ViewHolderholder=null;switch(viewType){caseTYPE_TEXT:view=LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_text,parent,false);holder=newMyTextHolder(view);break;caseTYPE_IMAGE:view=LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_image,parent,false);holder=newMyImageHolder(view);break;}returnholder;}}privateclassMyTextHolderextendsRecyclerView.ViewHolder{privateTextViewtextView;publicMyTextHolder(ViewitemView){super(itemView);textView=(TextView)itemView.findViewById(R.id.textView);}}privateclassMyImageHolderextendsViewHolder{privateImageViewimageView;publicMyImageHolder(ViewitemView){super(itemView);imageView=(ImageView)网站mView.findViewById(R.id.imageView);}}自定义BaseAdapter在自定义基类之前,先简单分析一下。我们需要自定义一个支持单一视图的Adapter,还需要自定义一个支持多种视图类型的Adapter。Adapter,两个类都必须继承BaseAdapter,首先提取两个类的公共部分定义为MyAdapterpublicabstractclassMyAdapterextendsBaseAdapter{protectedListdataList=newArrayList<>();protectedContextcontext;protectedLayoutInflaterinflater;publicMyAdapter(Contextcontext){this.context=context;inflater=LayoutInflater.from(context);}publicvoidsetDataList(ListdataList){this.dataList=dataList;notifyDataSetChanged();}@OverridepublicintgetCount(){if(null==dataList){return0;}returndataList.size();}@OverridepublicTgetItem(intposition){returndataList.get(position);}@OverridepubliclonggetItemId(intposition){returnposition;}}RecyclerView的Adapter实现中没有getView()方法。下面我们就来分析getView()方法是如何拆分的。一般我们实现getView()方法如下。publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ViewHolderholder=null;if(null==convertView){//填充布局convertView=inflater.inflate(R.layout.item_layout,parent,false);holder=newViewHolder();//通过ID查询控制holder.textView=(TextView)convertView.findViewById(R.id.textView);holder.imageView=(ImageView)convertView.findViewById(R.id.imageView);convertView.setTag(holder);}else{holder=(ViewHolder)convertView.getTag();}//赋值逻辑returnconvertView;}//一个空的ViewHolderpublicstaticclassViewHolder{TextViewtextView;ImageViewimageView;}Java编程是一种流行的编程方式,不就是面向接口的编程吗,在Android开发中还有一种开发方式叫做面向Holder编程。上面的代码是传统的ViewHolder实现方式。总之,它没有执行它。它作为载体来承载我们需要的控件。我们让ViewHolder做更多的事情,把convertView==null情况下需要做的大部分逻辑放到ViewHolder中。publicclassViewHolder{privatefinalViewitemView;publicViewHolder(ViewitemView){if(null==itemView){thrownewIllegalArgumentException("itemViewmustnotbenull");}else{this.itemView=itemView;itemView.setTag(this);}}publicViewgetItemView(){returnitemView;}}ViewHolder中的itemView就是getView()方法中的convertView,正好是item的根View,类似于RecyclerView中ViewHolder构造方法中的itemView。由于不同的视图需要创建不同的ViewHolder,我们可以将创建ViewHolder的方法设置为一个抽象方法并暴露出来。另外,在赋值的时候,我们还需要根据具体的业务进行赋值,还要设置一个抽象方法。publicabstractclassSimpleAdapterextendsMyAdapter{publicSimpleAdapter(Contextcontext){super(context);}publicViewgetView(intposition,ViewconvertView,ViewGroupparent){VHholder=null;if(null==convertView){holder=onCreateViewHolder(parent);convertView=holder.getItemView();}else{holder=(VH)convertView.getTag();}onBindViewHolder(holder,position);returnconvertView;}publicabstractvoidonBindViewHolder(VHholder,intposition);publicabstractVHonCreateViewHolder(ViewGroupparent);}在设置多个视图Adapter的类型,只需要在创建ViewHolder的时候额外传入一个viewType参数即可。publicabstractclassMultiAdapterextendsMyAdapter{publicMultiAdapter(Contextcontext){super(context);}@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){ViewHolderholder=null;if(null==convertView){holder=onCreateViewHolder(parent,getItemViewType(位置));convertView=holder.getItemView();}else{holder=(ViewHolder)convertView.getTag();}onBindViewHolder(holder,position);returnconvertView;}publicabstractvoidonBindViewHolder(ViewHolderholder,intposition);publicabstractViewHolderonCreateViewHolder(ViewGroupparent,intviewType);}自定义BaseAdapter的使用单视图类型SimpleAdapter使用publicclassTextAdapterextendsSimpleAdapter{publicTextAdapter(Contextcontext){super(context);}@OverridepublicvoidonBindViewHolder(TextHolderholder.intViewposition)(TextHolderholder.intViewposition)(TextHolderholder,intViewposition));}@OverridepublicTextHolderonCreateViewHolder(ViewGroupparent){ViewconvertView=inflater.inflate(R.layout.item_text,parent,false);returnnewTextHolder(convertView);}staticclassTextHolderextendsViewHolder{publicTextViewtextView;publicTextHolder(ViewitemView){super(itemView);textView=(TextView)itemView.findViewById(R.id.textView);}}}这里我们使用了两个泛型类型,一个是ViewHolder支持的数据类型String,一个是我们需要创建的ViewHolder,这样onCreateViewHolder方法中的返回值会自动返回到我们自定义的ViewHolder。更多关于泛型的知识可以参考JavaGenericsUsingparsing,单视图类型Adapter的使用比RecyclerView的Adapter方便多了多视图类型的使用publicclassRichAdapterextendsMultiAdapter{privatestaticfinalintTEXT=0;privatestaticfinalintPIC=1;publicRichAdapter(Contextcontext){super(context);}@OverridepublicintgetViewTypeCount(){return2;}@OverridepublicintgetItemViewType(intposition){if(position%3==0){returnPIC;}else{returnTEXT;}}@OverridepublicvoidonBindViewHolder(ViewHolderholder,intposition){switch(getItemViewType(position)){caseTEXT:TextHoldertextHolder=(TextHolder)holder;textHolder.textView.setText(getItem(position));中断;casePIC:ImageHolderimageHolder=(ImageHolder)holder;imageHolder.imageView.setImageResource(R.drawable.image);break;}}@OverridepublicViewHolderonCreateViewHolder(ViewGroupparent,intviewType){ViewitemView=null;ViewHolderholder=null;switch(viewType){caseTEXT:itemView=inflater.inflate(R.layout.item_text,parent,false);holder=newTextHolder(itemView);break;casePIC:itemView=inflater.inflate(R.layout.item_image,parent,false);holder=newImageHolder(itemView);break;}returnholder;}privatestaticclassTextHolderextendsViewHolder{TextViewtextView;publicTextHolder(ViewitemView){super(itemView);textView=(TextView)itemView.findViewById(R.id.textView);}}privatestaticclassImageHolderextendsViewHolder{ImageViewimageView;publicImageHolder(ViewitemView){super(itemView);imageView=(ImageView)itemView.findViewById(R.id.imageView);}}}这里的用法和RecyclerView几乎一样,唯一不同的是多写了一个getViewTypeCount()方法,当ListView或GridView使用BaseAdapter实现多类型视图时,必须重写该方法