之前很长时间都是使用的listview,然后自己写适配器,主要都是继承自BaseAdapter。大致的思路呢,就是我们传入数据源以及上下文对象,然后我们在自定义适配器文件中实现了构造方法,然后将传入的上下文对象(context)以及数据源初始化,下一步就是实现了我们继承自BaseAdapter的四个抽象方法:
1.getCount,返回的对象是数据源的大小;
2.getItem,返回的是每一项数据(datas.get(position));
3.getItemId,这个参数并没有深入去理解过,只是知道返回的参数是position;
4,getView,这个方法是主要的方法,我们的一系列赋值操作都是在这里来完成的,在这里面,我们通过convertview的复用来优化listview,通过布局映射器(layoutInflater)来将每个item的布局映射进来,然后通过findviewbyid初始化各个控件。此外,我们还使用到了viewHolder来优化listview。
之所以在理解recycleview的adapter之前提这么多list view的adapter,是因为为了对比着来理解,因为recycleview并没有那么成熟的系统的adapter来供我们使用,给了我们高度自由化的空间。
相比于listview继承的是baseAdapter,我们使用recycleview继承的是recycleview的adapter,这里我们需要传参数是我们自定义的viewHolder,这个viewHolder是继承于recycle view 的viewholder,至于我们要在viewholder里面执行的操作,我们后面再说,首先说我们继承recycle view的adapter需要继承的方法:
1.onCreateViewHolder,这个方法就类似我们的getview方法,但只是执行简单的绑定视图操作;
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 多布局支持
if (mMultiTypeSupport != null) {
mLayoutId = viewType;
}
View itemView = mInflater.inflate(mLayoutId, parent, false);
return new ViewHolder(itemView);
}
这里的viewholder就是我们自定义的viewholder,在这里将视图传到我们的viewholder里面。
2.onBindViewHolder,这个方法主要是对数据进行赋值操作,它的两个参数分别为(viewholder,T)我们通过viewholder拿到控件,后面的为数据,然后执行了一些正常的控件赋值操作。
3.getItemCount,返回的是数据源的大小,类似于list view的adapter的getCount;
当我们封装通用adapter的时候,就是在bind方法里面执行我们的抽象方法。
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// 设置点击和长按事件
if (mItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemClickListener.onItemClick(position);
}
});
}
if (mLongClickListener != null) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return mLongClickListener.onLongClick(position);
}
});
}
if(mHoverListener!=null){
holder.itemView.setOnHoverListener(new View.OnHoverListener() {
@Override
public boolean onHover(View view, MotionEvent motionEvent) {
return mHoverListener.onHover(view,motionEvent);
}
});
}
// 绑定怎么办?回传出去
convert(holder, mDatas.get(position));
}
/**
* 利用抽象方法回传出去,每个不一样的Adapter去设置
* @param item 当前的数据
*/
public abstract void convert(ViewHolder holder, T item);
然后要说的就是我们的viewHolder类,我们可以新建文件来实现这个类,也可以写在我们的adapter里面。
1.首先是我们的构造方法,通过上面在create里面的应用,我们可以发现,我们的构造方法里面,必须有的参数,就是我们的view对象,就是将我们的视图映射器加载进来的视图传递到我们的viewholder中来,之前我们在listview里面是直接手写的各个item布局的控件,而这里,我们是直接传递进来,我们用一个容器来装载我们的子view。
// 用来存放子View减少findViewById的次数
private SparseArray mViews;
public ViewHolder(View itemView) {
super(itemView);
mViews = new SparseArray<>();
}
2.一个主要的方法,getView,就是通过这个方法,我们实现了寻找控件并绑定
/**
* 通过id获取view
*/
public T getView(int viewId) {
// 先从缓存中找
View view = mViews.get(viewId);
if (view == null) {
// 直接从ItemView中找
view = itemView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
3.其他的就是我们就行的一些简单的赋值操作,包括文本以及图片,这里以textview为例:
/**
* 设置TextView文本
*/
public ViewHolder setText(int viewId, CharSequence text) {
TextView tv = getView(viewId);
tv.setText(text);
return this;
}
至此,简单的理解就这样了,至于添加事件监听,可以查看下面的全部代码:
package com.meng.yao.baselibrary.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* 项目名称:joke
* 类描述:万能RecyclerView适配器
* 创建人:woochen123
* 创建时间:2017/5/23 18:32
*/
public abstract class CommonRecyclerAdapter extends RecyclerView.Adapter {
protected Context mContext;
private LayoutInflater mInflater;
//数据怎么办?利用泛型
protected List mDatas;
// 布局怎么办?直接从构造里面传递
private int mLayoutId;
// 多布局支持
private MultiTypeSupport mMultiTypeSupport;
public CommonRecyclerAdapter(Context mContext, List mDatas, int mLayoutId) {
this.mContext = mContext;
this.mDatas = mDatas;
this.mLayoutId = mLayoutId;
this.mInflater = LayoutInflater.from(mContext);
}
/**
* 多布局支持
*/
public CommonRecyclerAdapter(Context context, List data, MultiTypeSupport multiTypeSupport) {
this(context, data, -1);
this.mMultiTypeSupport = multiTypeSupport;
}
/**
* 根据当前位置获取不同的viewType
*/
@Override
public int getItemViewType(int position) {
// 多布局支持
if (mMultiTypeSupport != null) {
return mMultiTypeSupport.getLayoutId(mDatas.get(position), position);
}
return super.getItemViewType(position);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 多布局支持
if (mMultiTypeSupport != null) {
mLayoutId = viewType;
}
View itemView = mInflater.inflate(mLayoutId, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// 设置点击和长按事件
if (mItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemClickListener.onItemClick(position);
}
});
}
if (mLongClickListener != null) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return mLongClickListener.onLongClick(position);
}
});
}
if(mHoverListener!=null){
holder.itemView.setOnHoverListener(new View.OnHoverListener() {
@Override
public boolean onHover(View view, MotionEvent motionEvent) {
return mHoverListener.onHover(view,motionEvent);
}
});
}
// 绑定怎么办?回传出去
convert(holder, mDatas.get(position));
}
/**
* 利用抽象方法回传出去,每个不一样的Adapter去设置
* @param item 当前的数据
*/
public abstract void convert(ViewHolder holder, T item);
@Override
public int getItemCount() {
return mDatas.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
// 用来存放子View减少findViewById的次数
private SparseArray mViews;
public ViewHolder(View itemView) {
super(itemView);
mViews = new SparseArray<>();
}
/**
* 设置TextView文本
*/
public ViewHolder setText(int viewId, CharSequence text) {
TextView tv = getView(viewId);
tv.setText(text);
return this;
}
/**
* 通过id获取view
*/
public T getView(int viewId) {
// 先从缓存中找
View view = mViews.get(viewId);
if (view == null) {
// 直接从ItemView中找
view = itemView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
/**
* 设置View的Visibility
*/
public ViewHolder setViewVisibility(int viewId, int visibility) {
getView(viewId).setVisibility(visibility);
return this;
}
/**
* 设置ImageView的资源
*/
public ViewHolder setImageResource(int viewId, int resourceId) {
ImageView imageView = getView(viewId);
imageView.setImageResource(resourceId);
return this;
}
/**
* 设置条目点击事件
*/
public void setOnIntemClickListener(View.OnClickListener listener) {
itemView.setOnClickListener(listener);
}
/**
* 设置条目长按事件
*/
public void setOnIntemLongClickListener(View.OnLongClickListener listener) {
itemView.setOnLongClickListener(listener);
}
/**
* 设置条目悬浮事件
* @param hoverListener
*/
public void setmHoverListener(View.OnHoverListener hoverListener){
itemView.setOnHoverListener(hoverListener);
}
}
/*
* 设置条目点击和长按事件
*/
public OnItemClickListener mItemClickListener;
public OnLongClickListener mLongClickListener;
public View.OnHoverListener mHoverListener;
public void setOnItemClickListener(OnItemClickListener itemClickListener) {
this.mItemClickListener = itemClickListener;
}
public void setOnLongClickListener(OnLongClickListener longClickListener) {
this.mLongClickListener = longClickListener;
}
public void setmHoverListener(View.OnHoverListener hoverListener){
this.mHoverListener = hoverListener;
}
}
这里的全部代码,实现了多布局支持,只是多布局这块,本人也不是很理解,就只是贴代码,就不作陈述了。