RecycleView的使用初次见面
首先了解桥梁—适配器:
RecycleView.Adapter
最初,我们先了解Adapter的常规使用。
正常境况下,我们至少要实现3个抽象方法,分别是:
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
public void onBindViewHolder(ViewHolder holder, int position)
public int getItemCount()
上面三个方法则是必须要实现的,但是如果要一个完善的Adapter上面3个方面绝对是不够的,关于其他的方法我们稍后再做说明。
我们分别对上面三个方法做深入的解释。
OnCreateViewHolder(ViewGroup parent,int viewType)
对于这个方法,其实我们从名字就可以知道大概它是做什么的,什么时候去调用。但是对于一些细节的东西,如果不做深究,或许用起来也稍显吃力。比如parent是什么?viewType又是什么?为什么只要写了这个返回就可以自动帮我们返回我们的ViewHolder?这些,我觉得作为一个有思想的Android开发工程师来说,是有必要清楚的。
当然。再多道理不如先看代码。当然如何看代码也是一个很有意思的事?一个RecycleView的代码可是10276行,要是一行一行的看,也是相当要命的。
我们的目的是要研究onCreateViewHolder(),那么我们势必要在RecycleView中找到这个方法。
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
正如我们所想,它是一个抽象方法。因为该方法的返回结果是与我们的需求相关,而与类本身没有太大的关系,其结果却与类相关。当然这个方法的实现要交由子类的实现。还有,从这个方法的名称我们就应该猜到这个类中一定有一个方法createViewHolder(),而且这个方法内就会调用onCreateViewHolder()方法。
public final VH createViewHolder(ViewGroup parent, int viewType) {
TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
final VH holder = onCreateViewHolder(parent, viewType);
holder.mItemViewType = viewType;
TraceCompat.endSection();
return holder;
}
上面的方法很简单,就是调用onCreateViewHolder()方法 并返回封装后的数据,很明显,到目前我们并得不到太多我们所需要的信息,所以,我觉得我们还要继续查找,找到方法调用链的上级。
View getViewForPosition(int position, boolean dryRun){
…
final int type = mAdapter.getItemViewType(offsetPosition);
…
if (holder == null) {
holder = mAdapter.createViewHolder(RecyclerView.this, type);
}
…
}
看到这个方法,我们终于可以得到很多我们想得到的信息。下面我们慢慢分析这短短的几句中蕴含的玄机,当然上面的代码是我极其精简的截取,如果想要更细致的了解,可以查看源码RecycleView.java中的第4366行起—4509行终
1.首先,我们要了解一个事实,那就是RecycleView其本身就是一个ViewGroup。
2.onCreateViewHolder(ViewGroup parent,int viewType) 该方法中的parent其实就是RecycleView本身,而viewType就是当前item的view类型。
3.细心的你要是打开mAdapter.getItemViewType(offsetPosition) 的方法实现,你会得到只有一行的代码,那就是return 0;也就是说默认情况下,它会返回0,如果你想让你的RecycleView支持多类型的itemView 你就可以通过重写getItemViewType()方法,为每一个item去指定类型,但是为了让你不同的view有不同的对待的话,你需要自己处理这些逻辑。下面给出一个stackoverflow中的大神给出的一个例子:
public class GroupViewHolder extends RecyclerView.ViewHolder {
TextView mTitle;
TextView mContent;
public GroupViewHolder(View itemView) {
super (itemView);
// init views...
}
}
public class ImageViewHolder extends RecyclerView.ViewHolder {
ImageView mImage;
public ImageViewHolder(View itemView) {
super (itemView);
// init views...
}
}
private static final int TYPE_IMAGE = 1;
private static final int TYPE_GROUP = 2;
@Override
public int getItemViewType(int position) {
// here your custom logic to choose the view type
return position == 0 ? TYPE_IMAGE : TYPE_GROUP;
}
@Override
public void onBindViewHolder (ViewHolder viewHolder, int i) {
switch (viewHolder.getItemViewType()) {
case TYPE_IMAGE:
ImageViewHolder imageViewHolder = (ImageViewHolder) viewHolder;
imageViewHolder.mImage.setImageResource(...);
break;
case TYPE_GROUP:
GroupViewHolder groupViewHolder = (GroupViewHolder) viewHolder;
groupViewHolder.mContent.setText(...)
groupViewHolder.mTitle.setText(...);
break;
}
}
从上面的代码,你就可以读到,当position = 0时为图片类型,非0时就是我们需要的列表类型,这样就可以制作出相当灵活的列表。但是你必须要自己处理这些灵活的逻辑,比如在数据绑定方法中,你需要分别进行数据的初始化工作。
下面介绍第二个方法:
public void onBindViewHolder(ViewHolder holder, int position)
其实对onCreateViewHolder()的解释,其实就是一句话,就是获取我们每个item的ViewHolder。
所以该方法的名字也就是onCreateViewHolder,联想一下我们对listview的使用,我们就很清楚下一步我们需要做那些工作—那就是对每个viewHolder 进行数据的初始化,对应于我们现在使用的这个view而言就是使用onBindViewHolder,该方法相当与一个桥梁的作用,也就是说使用这个方法,把数据与view进行了结合。
下面介绍最后一个方法啊:
public int getItemCount()
该方法比较简单,就是需要返回item的数量。