一个追求通用调用极简的RecyclerView适配器
来源:互联网 发布:ubuntu使用数据库 编辑:程序博客网 时间:2024/06/05 10:29
RecyclerView使用时,我们通常的业务数据是同类型的,比如都是订单数据,或者都是联系人数据
但有时候我们的数据源可能是不同搞得业务数据,比如文件管理器,每个Itemt条目可能是文件夹,也可能是文件,
并且文件和文件夹的交互也不同,这时相应的视图itemView就是不同的
这两种情况如何兼容到一块?
适配器的职责无非就是创建视图,绑定数据。由特殊到一半,我们先只考虑同类型数据下的适配器:
package com.sun.testrecycleadapter;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.ViewGroup;import java.util.ArrayList;import java.util.List;/** * recycleView的通用适配器 * 主要职责:接收item事件监听,数据crud * 对于创建视图绑定数据,给出通用的逻辑 * * @param <T> */public abstract class BaseRecycleAdapter<T> extends RecyclerView.Adapter<RecycleViewHolder>{ List<T> mDatas; Context mContext; int viewId; private int layoutId = -1; RecycleViewHolder.OnItemClickListener mOnItemClickListener; RecycleViewHolder.OnItemWidgetClickListener mOnItemWidgetClickListener; /** * item点击事件监听 */ public void setOnItemClickListener(RecycleViewHolder.OnItemClickListener onItemClickListener) { this.mOnItemClickListener = onItemClickListener; } /** * item中子控件的点击事件监听 * * @param viewId 子控件id */ public void setOnItemWidgetClickListener(int viewId, RecycleViewHolder.OnItemWidgetClickListener itemWidgetClickListener) { this.mOnItemWidgetClickListener = itemWidgetClickListener; this.viewId = viewId; } public void setLayoutId(int layoutId) { this.layoutId = layoutId; } BaseRecycleAdapter(Context context) { mContext = context; mDatas = new ArrayList<>(); } @Override public RecycleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (layoutId == -1) { throw new IllegalArgumentException("please setLayoutId before you setAdapter"); } RecycleViewHolder holder = RecycleViewHolder.get(mContext, parent, layoutId); holder.setOnClickListener(mOnItemClickListener); holder.setOnItemWidgetClickListener(viewId, mOnItemWidgetClickListener); return holder; } @Override public void onBindViewHolder(RecycleViewHolder holder, int position) { if (mDatas.size() == 0) { return; } bindData(holder, mDatas.get(position)); } public abstract void bindData(RecycleViewHolder holder, T t); @Override public int getItemCount() { return mDatas.size(); } /** * 添加一个数据对象 * * @param position 添加对象的位置 * @param t 泛型数据 */ public void addData(int position, T t) { mDatas.add(position, t); notifyItemInserted(position); } /** * 添加批量数据对象 * * @param postionStart 添加的起始位置 * @param list 被添加的数据源 */ public BaseRecycleAdapter addDataRange(int postionStart, List<T> list) { mDatas.addAll(postionStart, list); if (mDatas.size() == list.size()) { notifyDataSetChanged(); return this; } notifyItemRangeInserted(postionStart, list.size()); return this; } /** * 清除所有数据对象 * * @return */ public BaseRecycleAdapter clear() { mDatas.clear(); notifyDataSetChanged(); return this; } /** * 移除某个位置的数据对象 * * @param position */ public void removeData(int position) { mDatas.remove(position); notifyItemRemoved(position); } /** * 获取某个位置数据对象 * * @param pos * @return */ public T getData(int pos) { return mDatas.get(pos); } /** * 返回数据集合 * * @return */ public List<T> getDatas() { return mDatas; }}
上面的适配器是一个功能完整的基类适配器(不完整可后续补充),具有的功能有:
接受item事件监听,包括item自身点击,长按,子控件点击事件
对于创建视图和数据绑定,给出通用的逻辑
对于数据集合的增删操作。
接下来如果我们需要联系人列表:
package com.sun.testrecycleadapter;import android.content.Context;/** * 联系人适配器,只关注绑定数据 */public class ContactAdapter extends BaseRecycleAdapter<Contact>{ ContactAdapter(Context context) { super(context); } @Override public void bindData(RecycleViewHolder holder, Contact contact) { holder.setText(R.id.tv_contactName, contact.getName()); }}
可以看出具体的适配器只需做绑定数据的操作了。
联系人业务bean如下:
package com.sun.testrecycleadapter;public class Contact{ private String name; private String phone; public Contact(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; }}
那么调用呢?
ContactAdapter contactAdapter = new ContactAdapter(this);contactAdapter.setLayoutId(R.layout.item_contact);contactAdapter.addDataRange(0, contacts);contactAdapter.setOnItemClickListener(new RecycleViewHolder.OnItemClickListener(){ @Override public void onItemClick(View view, int position) { Toast.makeText(MainActivity.this, "onItemclick:" + position, Toast.LENGTH_SHORT).show(); } @Override public void onItemLongClick(View view, int position) { Toast.makeText(MainActivity.this, "onLongClick:" + position, Toast.LENGTH_SHORT).show(); }});contactAdapter.setOnItemWidgetClickListener(R.id.tv_contactName, new RecycleViewHolder.OnItemWidgetClickListener(){ @Override public void onItemWidgetClick(View view, int position) { Toast.makeText(MainActivity.this, "childViewClick:" + position, Toast.LENGTH_SHORT).show(); }});mRecyclerView.setAdapter(contactAdapter);可以概括为这几步:设置视图布局,设置数据源,设置需要的事件监听。
这样一个对于相同数据类型的适配器就处理完了。
那么对于多类型数据如何处理。还是那句话,适配器的最主要职责就是创建视图,绑定数据。
既然不同的数据类型决定了不同的视图结构,那么我们定义一个多视图基类extends 上面基类,复写onCreatViewHolder()即可
package com.sun.testrecycleadapter;import android.content.Context;import android.view.ViewGroup;/** * 主要职责:复写onCreateViewHolder,负责创建不同类型的tiem * @param <T> */abstract class MultiItemAdapter<T> extends BaseRecycleAdapter<T>{ interface MultiItemTypeSupport<T> { int getItemViewType(T t);//根据业务bean返回对应的itemView类型 int getLayoutId(int itemType);//根据itemView类型返回布局文件id } private MultiItemTypeSupport<T> mMultiItemTypeSupport; MultiItemAdapter(Context context, MultiItemTypeSupport<T> multiItemTypeSupport) { super(context); mMultiItemTypeSupport = multiItemTypeSupport; if (mMultiItemTypeSupport == null) throw new IllegalArgumentException("the mMultiItemTypeSupport can not be null."); } @Override public RecycleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { setLayoutId(mMultiItemTypeSupport.getLayoutId(viewType)); return super.onCreateViewHolder(parent,viewType); } @Override public int getItemViewType(int position) { return mMultiItemTypeSupport.getItemViewType(mDatas.get(position)); }}
如果我们需要文件列表:
package com.sun.testrecycleadapter;import android.content.Context;class FileWrapAdapter extends MultiItemAdapter<FileWrap>{ FileWrapAdapter(Context context) { super(context, new MultiItemTypeSupport<FileWrap>() { @Override public int getItemViewType(FileWrap fileWrap) { return fileWrap.getFileType(); } @Override public int getLayoutId(int itemType) { if (itemType == FileWrap.TYPE_DIR) { return R.layout.item_dir; } else return R.layout.item_file; } }); } @Override public void bindData(RecycleViewHolder holder, FileWrap fileWrap) { switch (holder.getLayoutId()) { case R.layout.item_dir: //设置文件夹文件名 holder.setText(R.id.tv_fileName, "我是文件夾"); break; case R.layout.item_file: //设置文件名 String fileName = "a.txt"; holder.setText(R.id.tv_fileName, fileName); holder.setClickable(R.id.upload, true); break; } }}
可以看出我们除了必须要做的绑定数据外,额外需要做的就是区分视图。
FileWrap业务bean如下:
package com.sun.testrecycleadapter;public class FileWrap{ public static final int TYPE_DIR = 0;//文件夹 public static final int TYPE_FILE = 1;//文件 private int fileType; public int getFileType() { return fileType; } public void setFileType(int fileType) { this.fileType = fileType; }}
调用情况:
FileWrapAdapter fileWrapAdapter = new FileWrapAdapter(this);fileWrapAdapter.addDataRange(0, mFileWrapList);fileWrapAdapter.setOnItemClickListener(new RecycleViewHolder.OnItemClickListener(){ @Override public void onItemClick(View view, int position) { Toast.makeText(MainActivity.this, "onItemclick:" + position, Toast.LENGTH_SHORT).show(); } @Override public void onItemLongClick(View view, int position) { Toast.makeText(MainActivity.this, "onLongClick:" + position, Toast.LENGTH_SHORT).show(); }});fileWrapAdapter.setOnItemWidgetClickListener(R.id.upload, new RecycleViewHolder.OnItemWidgetClickListener(){ @Override public void onItemWidgetClick(View view, int position) { Toast.makeText(MainActivity.this, "childViewClick:" + position, Toast.LENGTH_SHORT).show(); }});mRecyclerView.setAdapter(fileWrapAdapter);这时的调用就只需设置数据集合,需要的监听,布局id的设置交由MultiItemAdapter处理了。
综上,BaseRecycleAdapter和MultiItemAdapter两个文件合起来使用就是兼容这种多数据类型的处理方案。
当数据单一时,直接继承BaseRecycleAdapter即可
当数据多类型是,继承MultiItemAdapter即可。
阅读全文
0 0
- 一个追求通用调用极简的RecyclerView适配器
- 通用的RecyclerView适配器.
- 一个适用于ListView/GridView/RecyclerView的通用适配器
- RecyclerView通用适配器的实现
- 打造RecyclerView的通用适配器
- 通用的RecyclerView Adapter适配器
- RecyclerView的通用适配器的高级使用
- Android RecyclerView通用适配器
- RecyclerView通用适配器
- android RecyclerView 通用适配器
- RecyclerView系列之一:打造RecyclerView通用的适配器BaseAdapter
- listview通用适配器和RecyclerView通用适配器
- Android RecyclerView简单通用适配器
- RecyclerView通用适配器Adapter,对Adapter的封装
- 为你的RecyclerView.Adapter添加通用DiffUtil适配器
- android 一个通用的 适配器 adapter
- recyclerview的适配器功能
- RecyclerView的适配器
- 欢迎使用CSDN-markdown编辑器
- jsp中生成的验证码和存在session里面的验证码不一致的处理
- 设计模式学习:状态模式
- C语言的字符串函数strcat()和strncat()
- ckeditor的使用(行距,上传图片,字体)
- 一个追求通用调用极简的RecyclerView适配器
- ckeditor的使用(行距,上传图片,字体)
- 机器学习第一篇——python开发环境的搭建
- git
- session有效期问题
- 欢迎使用CSDN-markdown编辑器
- 定位的基本使用
- NGUI UIcenterOnChild
- android开发之&android中的swift,kotlin基础语法(一)