您的位置:首页 > 产品设计 > UI/UE

BaseRecyclerViewAdapterHelper开源项目之BaseQuickAdapter源码学习BaseViewHolder扩展功能的实现代码学习(四)

2017-03-14 00:00 906 查看
摘要:BaseRecyclerViewAdapterHelper开源项目之BaseQuickAdapter源码学习BaseViewHolder扩展功能的实现代码学习(四)

version:2.8.5

更多分享请看:http://cherylgood.cn

今天我们来分析下BaseQuickAdapter是如何实现BaseViewHolder的可扩展性的。

看代码

publicabstractclassBaseQuickAdapter<T,KextendsBaseViewHolder>extendsRecyclerView.Adapter<K>{
从类的定义我们可以看到两个范型类型T、K,T是我们的数据源的类型,K就是我们的viewHolder了,你可以使用已提供好的BaseViewHolder,也可以通过继承BaseViewHolder来进行扩展。

接下来我们分析的入口点就是代码中是如何创建ViewHolder的。ViewHolder的创建是在onCreateViewHolder生命回调方法中调用的,我们来看源码:

@Override publicKonCreateViewHolder(ViewGroupparent,intviewType){ Log.d(TAG,"#testonCreateViewHolder"); KbaseViewHolder=null; this.mContext=parent.getContext(); this.mLayoutInflater=LayoutInflater.from(mContext); switch(viewType){ caseLOADING_VIEW: baseViewHolder=getLoadingView(parent); break; caseHEADER_VIEW: baseViewHolder=createBaseViewHolder(mHeaderLayout); break; caseEMPTY_VIEW: baseViewHolder=createBaseViewHolder(mEmptyLayout); break; caseFOOTER_VIEW: baseViewHolder=createBaseViewHolder(mFooterLayout); break; default: baseViewHolder=onCreateDefViewHolder(parent,viewType); } returnbaseViewHolder; }
里面每个case语句里的代码最终都会调用同一个方法:

/** *ifyouwanttousesubclassofBaseViewHolderintheadapter, *youmustoverridethemethodtocreatenewViewHolder. * *@paramviewview *@returnnewViewHolder */ protectedKcreateBaseViewHolder(Viewview){ Classtemp=getClass(); Classz=null; /** *检测当前类及其父类是否与BaseViewHolder相同或者具备相同接口如果具备,如果没有z==null */ while(z==null&&null!=temp){ z=getInstancedGenericKClass(temp); temp=temp.getSuperclass(); } Kk=createGenericKInstance(z,view); returnnull!=k?k:(K)newBaseViewHolder(view); }
里面主要是用了java的反射技术实现的。我们可以看到temp这个字段:

temp表示当前的实际类型;

可以看到里面调用了这么一句代码z=getInstancedGenericKClass(temp);

方法的代码如下,部分注释是我加上去的。

/** *getgenericparameterK * *@paramz *@return */ privateClassgetInstancedGenericKClass(Classz){ /** *ReturnstheTyperepresentingthedirectsuperclassoftheentity *(class,inte 7fe0 rface,primitivetypeorvoid)representedbythisClass. */ Typetype=z.getGenericSuperclass(); /** *ParameterizedTyperepresentsaparameterizedtypesuchasCollection<String>. */ if(typeinstanceofParameterizedType){ /** *getActualTypeArguments() * *ReturnsanarrayofTypeobjectsrepresentingtheactual *typeargumentstothistype. */ Type[]types=((ParameterizedType)type).getActualTypeArguments(); for(Typetemp:types){ if(tempinstanceofClass){ ClasstempClass=(Class)temp; //判断tempClass是否是BaseViewHolder类型相同或具有相同的接口 if(BaseViewHolder.class.isAssignableFrom(tempClass)){ returntempClass; } } } } returnnull; }
里面的Typetype=z.getGenericSuperclass();返回z的父类类型,包括实现的接口类型等。所以z是个集合。 我们对其进行遍历:
Type[]types=((ParameterizedType)type).getActualTypeArguments(); for(Typetemp:types){ if(tempinstanceofClass){ ClasstempClass=(Class)temp; //判断tempClass是否是BaseViewHolder类型相同或具有相同的接口 if(BaseViewHolder.class.isAssignableFrom(tempClass)){ returntempClass; } } }
首先判断其是否是一个类类型:tempinstanceofClass 如果是,判断是否是BaseViewHolder类型相同或具有相同的接口,是的话返回,不是返回null:
if(BaseViewHolder.class.isAssignableFrom(tempClass)){ returntempClass; }
所以protectedKcreateBaseViewHolder(Viewview)方法中的while循环的作用就是 不断遍历当前类的父类。判断其父类是否是BaseViewHolder的子类,代码如下:
while(z==null&&null!=temp){ z=getInstancedGenericKClass(temp); temp=temp.getSuperclass(); }
最终z里面存储的是我们的BaseViewHolder类字节码或者是继承自BaseViewHolder的类的字节码; 拿到类的字节码后我们就要实例化它了: 实例化时我们调用的是Kk=createGenericKInstance(z,view); 代码如下:
/** *trytocreateGenericKinstance * *@paramz *@paramview *@return */ privateKcreateGenericKInstance(Classz,Viewview){ try{ Constructorconstructor; Stringbuffer=Modifier.toString(z.getModifiers()); StringclassName=z.getName(); //innerandunstaticclass if(className.contains("$")&&!buffer.contains("static")){ constructor=z.getDeclaredConstructor(getClass(),View.class); return(K)constructor.newInstance(this,view); }else{ constructor=z.getDeclaredConstructor(View.class); return(K)constructor.newInstance(view); } }catch(NoSuchMethodExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); }catch(InstantiationExceptione){ e.printStackTrace(); }catch(InvocationTargetExceptione){ e.printStackTrace(); } returnnull; }
里面主要做了两个操作:1、我们的类是否是内部类且非晶态内部类,是,按内部类的实例化步骤处理,2、按正常类型进行处理。 1、先获取className,如果是内部类。类名会包含有$符号且不包含static 最终如果实例化成功会返回实例化的对象,否则返回null 所以最终我们最后的代码是一个三目运算符,
returnnull!=k?k:(K)newBaseViewHolder(view);
如果前面实例化返回null,我们会默认返回一个
newBaseViewHolder(view);

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐