代码如下:
首先介绍一下RecyclerView的常规用法:
package com.crs.demo.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.crs.demo.R;
import java.util.ArrayList;
/**
* Created on 2016/9/8.
* Author:crs
* Description:RecyclerView的adapter
* 1)自定义Adapter继承自RecyclerView.Adapter 记住是哪个包下的adapter.RecyclerView.Adapter是抽象类,必须实现其中的抽象方法.
* 2)给RecyclerView.Adapter设置泛型类型,为<自定义adapter.自定义Viewholder>(固定格式)
* 3)自定义ViewHolder继承自RecyclerView.ViewHolder,记住是RecyclerView下的ViewHolder
* 4)onCreateViewHolder()方法的返回值类型为<自定义adapter.自定义Viewholder> onBindViewHolder()方法里面的holder类型也是<自定义adapter.自定义Viewholder>
* 要不然找不到控件的
* 5)定义的ViewHolder是一个内部类,RecyclerView.Adapter在继承时需要指定泛型.要制定ViewHolder是谁的内部类.
* 6)记住这三个方法onCreateViewHolder() onBindViewHolder() getItemCount() LinearLayoutManager RecyclerView.Adapter RecyclerView.ViewHolder
* 7)itemView 指代当前条目。需要一个ViewHolder,就创建并返回。
* 8)RecyclerView的使用,先设置布局管理器,在设置适配器。
*/
public class TestRecyclerAdapter extends RecyclerView.Adapter<TestRecyclerAdapter.ViewHolder> {
private ArrayList<String> list;
private LayoutInflater mInflate;
public TestRecyclerAdapter(Context context, ArrayList<String> list) {
this.list = list;
mInflate = LayoutInflater.from(context);
}
@Override
public TestRecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflate.inflate(R.layout.item_test_recycler, null);
ViewHolder myHolder = new ViewHolder(view);
return myHolder;
}
@Override
public void onBindViewHolder(TestRecyclerAdapter.ViewHolder holder, int position) {
String title = list.get(position);
holder.tv.setText(title);
}
@Override
public int getItemCount() {
return list.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public ViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv);
}
}
}
BaseAdapter的封装:
主要有两大功能:
1)通过抽象方法绑定数据
2)通过接口回调设置点击事件
对RecyclerView.Adapter进行封装
对RecyclerView.ViewHolder进行封装
package com.crs.demo.base;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
/**
* Created on 2016/9/8.
* Author:crs
* Description:BaseAdapter
* 1)在创建继承自BaseAdapter的类的时候,指定传递的数据类型和ViewHolder类型
* 2)抽象方法中为什么药传递holder参数,因为要实例化控件.
* 3)定义接口,添加条目点击事件的公共回调方法,接口里面的抽象方法什么时候调用? 条目点击的时候,条目点击在BaseViewHolder里面
* 所以必须通过构造函数传递过去.
* 4)在不确定类型的时候,使用泛型来标识.每次传递的数据类型不确定,所以使用泛型。
* 5)抽取公共的事情,让父类来做,比如:根据id创建view,条目的点击事件,绑定数据.
* 6)基类里面提供常用的方法。
* 7)抽取与封装是不一样的。 向上抽去基类。(子类原来越少,而父类越来越多)
*/
public abstract class BaseAdapter<T, H extends BaseViewHolder> extends RecyclerView.Adapter<BaseViewHolder> {
//由于需要让子类继承,所以不能私有.
public List<T> list;
public LayoutInflater mInflate;
public int mLayoutResId;
//初始化父类的构造方法,让子类创建对象的时候,调用
public BaseAdapter(List<T> list, Context context, int mLayoutResId) {
this.list = list;
this.mInflate = LayoutInflater.from(context);
this.mLayoutResId = mLayoutResId;
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflate.inflate(mLayoutResId, null);
//在构造方法里面传递接口对象
BaseViewHolder baseViewHolder = new BaseViewHolder(view, onItemClickListener);
return baseViewHolder;
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
//获取数据对象
T t = list.get(position);
//通过抽象方法对调进行对外暴露,用于绑定数据,让子类实现(数据、holder代表控件)
bindData(t, holder);
}
@Override
public int getItemCount() {
return list.size();
}
//定义一个抽象方法,让子类实现
public abstract void bindData(T t, BaseViewHolder holder);
//条目点击事件,接口回调。
private OnItemClickListener onItemClickListener;
public interface OnItemClickListener {
void OnItemClick(View view, int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
}
BaseViewHolder的封装:
package com.crs.demo.base;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
/**
* Created on 2016/9/8.
* Author:crs
* Description:BaseViewHolder
* 1)如何去获取控件以及确定控件类型,现在不清楚控件的类型以及数量.不能把控件写死,通过View数组来实现
* 2)<T extends View> T 定义返回值的泛型类型;在返回的时候,进行强转
*/
public class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
//用于存储条目中的控件
private final SparseArray<View> views;
private BaseAdapter.OnItemClickListener onItemClickListener;
//父类中只有有构造函数,子类在继承父类时,必须添加对应的构造函数
public BaseViewHolder(View itemView, BaseAdapter.OnItemClickListener onItemClickListener) {
super(itemView);
this.onItemClickListener = onItemClickListener;
views = new SparseArray<>();
//为条目设置点击事件
itemView.setOnClickListener(this);
}
//实例化控件
private <T extends View> T findView(int id) {
View view = views.get(id);
if (view == null) {
view = itemView.findViewById(id);
views.put(id, view);
}
return (T) view;
}
//对外提供公共的方法,去实例化控件
public View getViews(int id) {
return findView(id);
}
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.OnItemClick(v,getLayoutPosition());
}
}
}
使用:TextAdapter继承自BaseAdapter
package com.crs.demo.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import com.crs.demo.R;
import com.crs.demo.base.BaseAdapter;
import com.crs.demo.base.BaseViewHolder;
import java.util.List;
/**
* Created on 2016/9/8.
* Author:crs
* Description:TestAdapter
* 1)在继承的时候指定数据类型和BaseViewHolder类型
* 2)在自定义的adapter中哪些是变化的: 条目布局、集合里面存放的数据类型、控件数量以及控件类型
* 3)让自定义的Adapter实现抽象方法(数据绑定通过抽象方法来实现)
*/
public class TestAdapter extends BaseAdapter<String, BaseViewHolder> {
public TestAdapter(List<String> list, Context context) {
//需要传递一个条目布局进去
super(list, context, R.layout.item_test_adapter);
}
@Override
public void bindData(String s, BaseViewHolder holder) {
TextView tv = (TextView) holder.getViews(R.id.tv);
tv.setText(s);
}
}