本人之前也是不喜欢写博客,可是发现好多知识当时知道过了很长时间就会忘记,又得回去找资料看,最近看一些资料,觉得用recycleview每次写adapter 就很麻烦,看了不是的博客,自己也了已个通用的adapter,这个还是收到Darren的启发,确实要自己总结一下自己的知识,就写这个通用的adapter,第一次写写得不好,看到的希望对你有帮助,可以互相学习。
基本思路:
要让adapter通用的话,要解决布局,数据,r绑定怎么搞?数据的话可以通过泛型来传递,布局的话可以通过构造传,绑定显示就可以回传
1:改造adapter 下面是一个通用的adapter 他实现了单布局和多布局
/**
* Created by Administrator on 2017/7/11 0011.
*
* Description: 通用的Adapter
*/
public abstract class CommonAdapter<DATA> extends RecyclerView.Adapter<ViewHodle>{
private int mLayoutId;
protected List<DATA> mDatas;
private LayoutInflater mLayoutInfater;
private Context mContext;
private MulitiTypeSupport typeSupport;
//这个是普通布局就可以调用这个方法
public CommonAdapter(Context mContext,int mLayoutId, List<DATA> mDatas) {
mLayoutInfater = LayoutInflater.from(mContext);
this.mContext = mContext;
this.mLayoutId = mLayoutId;
this.mDatas = mDatas;
}
//这个是多布局
public CommonAdapter(Context mContext,List<DATA> mDatas, MulitiTypeSupport typeSupport ){
this(mContext,-1,mDatas);
this.typeSupport = typeSupport;
}
@Override
public ViewHodle onCreateViewHolder(ViewGroup parent, int viewType) {
if(typeSupport!=null){//需要多布局
mLayoutId = viewType;
}
View itemView = mLayoutInfater.inflate(mLayoutId,parent,false);
ViewHodle viewHodle = new ViewHodle(itemView);
return viewHodle;
}
@Override
public int getItemViewType(int position) {
//多布局用
if(typeSupport!=null){
return typeSupport.getLayoutId(mDatas.get(position));
}
return super.getItemViewType(position);
}
@Override
public void onBindViewHolder(ViewHodle holder, final int position) {
convert(holder,mDatas.get(position),position);
if(itemClickListeren!=null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
itemClickListeren.itemClick(position);
}
});
}
if(onItemLongClickListeren!=null){
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
onItemLongClickListeren.onItemLongClick(position);
return true;
}
});
}
}
//这个方法是把数据 ViewHolder 还有当前的位置传出去 实现在你自己的adapter里面
protected abstract void convert(ViewHodle holder, DATA data, int position);
@Override
public int getItemCount() {
return mDatas.size();
}
//recycleview的点击跟长按事件
private ItemClickListener itemClickListeren;
public void setOnItemClickListeren(ItemClickListener itemClickListeren){
this.itemClickListeren = itemClickListeren;
}
private OnItemLongClickLiateren onItemLongClickListeren;
public void setOnItemLongClickListeren(OnItemLongClickLiateren onItemLongClickListeren){
this.onItemLongClickListeren = onItemLongClickListeren;
}
//这个是数据刷新 添加数据
public void upData(List<DATA> mDatas){
this.mDatas = mDatas;
notifyDataSetChanged();
}
}
2:下面是我自己写的一个例子
/**
* Created by Administrator on 2017/7/11 0011.
* Description: 通用的Adapter
*/
//在集成通用的adapter的时候 数据传递是根据你自己的数据格式传递
public class TextAdapter extends CommonAdapter<A.Data> {
//我们继承的时候 会继承单布局 和多布局 这里是多布局
/*
* mContext 上下文
* mDatas 数据
* typeSupport 布局的类型
* 这里我们可以不用这种 直接 MulitiTypeSupport 这个直接new出来
*/
/* public TextAdapter(Context mContext, List<A.Data> mDatas, MulitiTypeSupport typeSupport) {
super(mContext, mDatas, typeSupport);
}*/
public TextAdapter(Context mContext, final List<A.Data> mDatas) {
super(mContext, mDatas, new MulitiTypeSupport<A.Data>() {
@Override
public int getLayoutId(A.Data item) {
//我这里只是用了2种布局
if (item.position == 1) {
return R.layout.item_1;
}
return R.layout.item_0;
}
});
}
// //我们继承的时候 会继承单布局 和多布局 这里是单布局 单布局实现就很简单了 数据
/*
* mContext 上下文
* mLayoutId 布局id
* mDatas 数据
*/
/*public TextAdapter(Context mContext, int mLayoutId, List<A.Data> mDatas) {
super(mContext, mLayoutId, mDatas);
}*/
/*
* holder viewholder
* data 数据
* position 当前的位置
*/
@Override
protected void convert(ViewHodle holder, A.Data data, int position) {
if (data.position == 1) {
holder.setText(R.id.tv1, data.content);
} else if (data.position == 0) {
holder.setText(R.id.tv0, data.content);
}
//这里是调用显示网络图片
// holder.setImagePath(R.id.tv0, data.content,new ImageLoad(data.content) ) }
3:最后就是ViewHolder 直接贴代码/* * 图片处理 * */ public class ImageLoad extends ViewHodle.HolderImageLoader { public ImageLoad(String path) { super(path); } @Override public void loadImage(Context context, ImageView imageView, String path) { //这里你可以用Glide 也可以用其他第三方的网络加载图片 Glide.with(context).load(path).into(imageView); } } }
/**
* Created by Administrator on 2017/7/11 0011.
* Description: RecyclerView的ViewHolder
*/
public class ViewHodle extends RecyclerView.ViewHolder{
//通过 SparseArray<View> 来缓存 不用每次都去findViewById
private SparseArray<View> mViews;
public ViewHodle(View itemView) {
super(itemView);
mViews = new SparseArray<>();
}
/*
* getView 这个方法是去 findViewById 不用你在外面去findViewById 减少代码
*
*/
public <T extends View> T getView(int viewId){
View view = mViews.get(viewId);
if(view == null){
view = itemView.findViewById(viewId);
mViews.put(viewId,view);
}
return (T)view;
}
/*
* setText 这个方法是直接调用设置TextView
* viewId TextView 的id
* text TextView 的数据
*/
public ViewHodle setText(int viewId,String text){
TextView view = getView(viewId);
view.setText(text);
return this;
}
//处理本地图片
public ViewHodle setImageResource(int viewId,int resource){
ImageView view =getView(viewId);
view.setImageResource(resource);
return this;
}
/**
* 设置图片通过路径,这里稍微处理得复杂一些,因为考虑加载图片的第三方可能不太一样
* 也可以直接写死
*/
public ViewHodle setImagePath(int viewId, String path,HolderImageLoader imageLoader){
ImageView view =getView(viewId);
//这里是写死的
// Glide.with(view.getContext()).load(path).into(view);
if(imageLoader == null) {
throw new NullPointerException("imageLoader is null!");
}
imageLoader.loadImage(view.getContext(),view,imageLoader.getmPath());
return this;
}
}
/**
* 图片加载,这里稍微处理得复杂一些,因为考虑加载图片的第三方可能不太一样
* 也可以不写这个类
*/
public abstract static class HolderImageLoader{
private String mPath;
public String getmPath() {
return mPath;
}
public HolderImageLoader(String path) {
this.mPath = path;
}
public abstract void loadImage(Context context,ImageView imageView,String path);
}
} 4:最后调用
/**
* Created by Administrator on 2017/7/11 0011.
*/
public class A extends AppCompatActivity{
private RecyclerView rl;
List<Data> list ;
private TextAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
list = new ArrayList<>();
for (int i=0;i<50;i++){
if(i%3==0){
list.add(new Data("我是布局1的数据"+i,1));
}else {
list.add(new Data("我是布局0的数据"+i,0));
}
}
rl = (RecyclerView) findViewById(R.id.recycle);
rl.setLayoutManager(new LinearLayoutManager(this));
adapter = new TextAdapter(this, list);
rl.setAdapter(adapter);
adapter.setOnItemClickListeren(new ItemClickListener() {
@Override
public void itemClick(int position) {
Toast.makeText(A.this,"你点击了第"+position+"个条目",Toast.LENGTH_SHORT).show();
}
});
adapter.setOnItemLongClickListeren(new OnItemLongClickLiateren() {
@Override
public void onItemLongClick(int position) {
Toast.makeText(A.this,"你长按了第"+position+"个条目",Toast.LENGTH_SHORT).show();
}
});
}
/*
* 这个方法是添加数据 这里没有上啦 就模拟点击加载数据
*/
public void n(View view) {
List<Data> da = new ArrayList<>();
for (int i=0;i<50;i++){
if(i%3==0){
da.add(new Data("我是添加布局1的数据"+i,1));
}else {
da.add(new Data("我是添加布局0的数据"+i,0));
}
}
list.addAll(da);
adapter.upData(list);
}
public class Data{
String content;
int position;
public Data(String content, int position) {
this.content = content;
this.position = position;
}
}
}
以上是全部代码 都测试过 单布局跟多布局