RecyclerIView作为ListView的替代者,优势在此就不做充分说明了,相信使用过RecyclerView的人来说,已经爱不释手了,一个控件可以解决这种列表,不管横向、纵向还是瀑布流,都可以很轻易即可实现,此处就通用的封装简单随笔记录。
通用holder的封装如下
package com.example.recyclerview.recyclerview;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by Administrator on 2018/5/25.
*/
public class RecyclerViewBaseHolder extends RecyclerView.ViewHolder{
private View mContentView;
//内存中缓存的view
private SparseArray<View> views;
private Context mContext;
public RecyclerViewBaseHolder(Context context,View itemView) {
super(itemView);
mContentView=itemView;
views=new SparseArray<>();
mContext=context;
}
public static RecyclerViewBaseHolder getHolder(Context context, ViewGroup parent,int layoutId){
View itemView= LayoutInflater.from(context).inflate(layoutId,parent,false);
return new RecyclerViewBaseHolder(context,itemView);
}
/**
*
* @param viewId 控件的id
* @param <T>
* @return 返回经强转成实际类型之后的view类型
* 本方法一般是在具体adapter中comvert()方法通过id查找对应控件所用
*/
public <T extends View> T get(int viewId){
View view=views.get(viewId);
if(view==null){
view=mContentView.findViewById(viewId);
views.put(viewId,view);
}
return (T)view;
}
/**
* 用于获取特定情况获取复用的itemView
* @return
*/
public View getContentView(){
return mContentView;
}
}
以上是一个通用的holder,改类中没有需要去复写的方法,只有一个getView方法在子类adapter中进行数据绑定时,对控件进行初始化才使用该方法。
通用adapter封装如下:
package com.example.recyclerview.recyclerview;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import java.util.ArrayList;
/**
* Created by Administrator on 2018/5/25.
*/
public abstract class RecyclerViewBaseAdapter<T> extends RecyclerView.Adapter<RecyclerViewBaseHolder> {
private ArrayList<T> datas;
private Context context;
private int layoutId;
public RecyclerViewBaseAdapter(ArrayList<T> datas, Context context, int layoutId) {
this.datas = datas;
this.context = context;
this.layoutId = layoutId;
}
@Override
public RecyclerViewBaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerViewBaseHolder holder=RecyclerViewBaseHolder.getHolder(context,parent,layoutId);
return holder;
}
@Override
public void onBindViewHolder(RecyclerViewBaseHolder holder, int position) {
convert(holder,datas.get(position),position);
}
@Override
public int getItemCount() {
return datas==null ? 0:datas.size();
}
public abstract void convert(RecyclerViewBaseHolder holder,T t,int postion);
}
封装好通用的adapter之后,我们实际业务子类adapter只需要集成通用adapter然后重写convert方法完成控件的初始化及数据绑定即可。
封装了通用的adapter,但是上面的adapter只是单视图类型,假如我们需要一个多类型条目的通用adapter该如何封装,下面我们可以思考一下,多条目类型跟单条目类型的不同,本质的不同其实就是视图的不同,而我们单条目通用的adapter是通过将layoutId传进来,然后返回不同的holder,而对于多条目来说,我们的视图具体展示是要通过viewtype类型决定的,而在onCreateVeiwHolder中有一个字段viewType正是我们的视图类型,所以这里我们可以提取一个抽象方法getLayoutId(int viewType)让子类具体去重写,重写的目的是根据viewType返回不同的layoutId,拿到layoutId之后的逻辑,就跟单条目是一样的,将layoutId传给holder去创建对应holder.那么如何拿到viewType,我们只需要重写getItemViewType即可,但是由于是封装通用的adapter,在adapter中我们无法去重写,所以也可以将这个方法封装成抽象,封装完了之后在通用adapter中的getItemViewType中去调用即可。考虑到定义两个抽象方法,我们此处不妨定义成接口,具体代码如下;
多条目类型接口:
package com.example.recyclerview.recyclerview;
import java.util.ArrayList;
/**
* Created by Administrator on 2018/5/25.
* 多条目类型的通用接口
*/
public interface MultiTypeSupportImp<T> {
/**
* 根据position对应的数据 判断返回对应的具体item的类型
*/
int getViewItemType(ArrayList<T> datas, int position);
/**
* 根据不同的类型返回不同布局id
*/
int getLayoutId(int viewType);
}
多条目类型的通用adapter
package com.example.recyclerview.recyclerview;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import java.util.ArrayList;
/**
* Created by Administrator on 2018/5/25.
* 多种条目类型的RecyclerView
*/
public abstract class MultiTypeViewBaseAdapter<T> extends RecyclerView.Adapter<RecyclerViewBaseHolder> implements MultiTypeSupportImp<T> {
private ArrayList<T> datas;
private Context context;
public MultiTypeViewBaseAdapter(ArrayList<T> datas, Context context) {
this.datas = datas;
this.context = context;
}
@Override
public RecyclerViewBaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layoutId=getLayoutId(viewType);
RecyclerViewBaseHolder holder=RecyclerViewBaseHolder.getHolder(context,parent,layoutId);
return holder;
}
@Override
public void onBindViewHolder(RecyclerViewBaseHolder holder, int position) {
convert(holder,datas.get(position),position);
}
@Override
public int getItemCount() {
return datas==null ? 0:datas.size();
}
@Override
public int getItemViewType(int position) {
return getViewItemType(datas,position);
}
@Override
public abstract int getViewItemType(ArrayList<T> datas, int position);
@Override
public abstract int getLayoutId(int viewType);
public abstract void convert(RecyclerViewBaseHolder holder,T t,int postion);
}