android RecycleView Adapter简单封装
早些时候我们使用系统提供个的BaseAdapter的时候为了满足大家的需要,我们总会对BaseAdapter做一层上层的封装,然后对于实际业务我们只需要关心getView里面的View即可,是代码可读性和可维护性更高,特别是在多View的界面,这个优势就体现出来了,自从Android 5.0后系统提供的,先不说效率如何,这个既然是Google为我们提供的,我们姑且用之,不过说实话,对于它的写法不习惯他的人看着很是麻烦,其实这个类无外乎继承自RecyclerView.Adapter然后提供一个HolderView。
如下:
public class DetailParamAdapter extends RecyclerView.Adapter<ParamHolderView> { private List<ProductParamEntity> list; private LayoutInflater mInflater; private Context mContext = null; public DetailParamAdapter(Context context) { this.mContext = context; mInflater = LayoutInflater.from(context); } public void setList(List<ProductParamEntity> list) { this.list = list; notifyDataSetChanged(); } public OnItemClickListener mOnItemClickListener; public interface OnItemClickListener { void onItemClick(View view, int position); } public void setOnItemClickListener(OnItemClickListener mOnItemClickLitener) { this.mOnItemClickListener = mOnItemClickLitener; } @Override public ParamHolderView onCreateViewHolder(ViewGroup parent, int viewType) { View view = mInflater.inflate(R.layout.item_product_param, parent, false); ParamHolderView holder = new ParamHolderView(view); return holder; } @Override public void onBindViewHolder(final ParamHolderView holder, final int position) { ProductParamEntity bean = list.get(position); if (bean != null) { holder.itemTitle.setText(bean.title); holder.itemContent.setText(bean.content); } } @Override public int getItemCount() { return list.size(); } } class ParamHolderView extends RecyclerView.ViewHolder { @BindView(R.id.item_title) TextView itemTitle; @BindView(R.id.item_content) TextView itemContent; public ParamHolderView(View itemView) { super(itemView); ButterKnife.bind(this, itemView); itemView.setTag(this); } }
不过我们可不可以对上面的写法来一个精简呢?
其实分析下,adapter对我们有用的就两个方法,一个是获取adapter的View,然后是绑定数据OnBindData,至于数据的来源,我们可以借鉴RecyclerView.Adapter做一个泛型。
有了上面的思路,首先我们要获取adapter的View,然后将它赋给onCreateViewHolder返回的view对象。所以我们的构造可以这么写,
public BaseRecycleAdapter(Context context, List<T> list, int... layoutIds) { this.mContext = context; this.mList = list; this.layoutIds = layoutIds; this.mLInflater = LayoutInflater.from(mContext); }
public BaseRecycleHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType < 0 || viewType > layoutIds.length) { throw new ArrayIndexOutOfBoundsException("layoutIndex"); } if (layoutIds.length == 0) { throw new IllegalArgumentException("not layoutId"); } int layoutId = layoutIds[viewType]; View view = mConvertViews.get(layoutId); if (view == null) { view = mLInflater.inflate(layoutId, parent, false); } BaseRecycleHolder viewHolder = (BaseRecycleHolder) view.getTag(); if (viewHolder == null || viewHolder.getLayoutId() != layoutId) { viewHolder = new BaseRecycleHolder(mContext, layoutId, view); return viewHolder; } return viewHolder; }
然后我们需要绑定界面了,由于各个页面的对于的元素不一样,所以这个方法我们需要根据实际情况去动态绑定数据,所以我们需要写一个抽象方法去让用户实现,这个抽象方法主要包含ViewHolder界面,位置,还有Item的元素(其实这个大可以不要)
protected abstract void onBindData(BaseRecycleHolder viewHolder, int position, T item);
@Override public void onBindViewHolder(BaseRecycleHolder holder, int position) { final T item = mList.get(position); onBindData(holder, position, item); }
当然我们这个Adapter基础的类可能还需要一些常用入add,clear,del等操作方法。其完整的代码如下:
public abstract class BaseRecycleAdapter<T> extends RecyclerView.Adapter<BaseRecycleHolder> implements RecyclerViewHelper<T> { protected Context mContext; protected List<T> mList; protected int[] layoutIds; protected LayoutInflater mLInflater; private SparseArray<View> mConvertViews = new SparseArray<>(); public BaseRecycleAdapter(Context context, List<T> list, int... layoutIds) { this.mContext = context; this.mList = list; this.layoutIds = layoutIds; this.mLInflater = LayoutInflater.from(mContext); } @Override public BaseRecycleHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType < 0 || viewType > layoutIds.length) { throw new ArrayIndexOutOfBoundsException("layoutIndex"); } if (layoutIds.length == 0) { throw new IllegalArgumentException("not layoutId"); } int layoutId = layoutIds[viewType]; View view = mConvertViews.get(layoutId); if (view == null) { view = mLInflater.inflate(layoutId, parent, false); } BaseRecycleHolder viewHolder = (BaseRecycleHolder) view.getTag(); if (viewHolder == null || viewHolder.getLayoutId() != layoutId) { viewHolder = new BaseRecycleHolder(mContext, layoutId, view); return viewHolder; } return viewHolder; } @Override public void onBindViewHolder(BaseRecycleHolder holder, int position) { final T item = mList.get(position); onBindData(holder, position, item); } @Override public int getItemCount() { return mList == null ? 0 : mList.size(); } @Override public int getItemViewType(int position) { return getLayoutIndex(position, mList.get(position)); } /** * 指定item布局样式在layoutIds的索引。默认为第一个 */ public int getLayoutIndex(int position, T item) { return 0; } protected abstract void onBindData(BaseRecycleHolder viewHolder, int position, T item); @Override public boolean addAll(List<T> list) { boolean result = mList.addAll(list); notifyDataSetChanged(); return result; } @Override public boolean addAll(int position, List list) { boolean result = mList.addAll(position, list); notifyDataSetChanged(); return result; } @Override public void add(T data) { mList.add(data); notifyDataSetChanged(); } @Override public void add(int position, T data) { mList.add(position, data); notifyDataSetChanged(); } @Override public void clear() { mList.clear(); notifyDataSetChanged(); } @Override public boolean contains(T data) { return mList.contains(data); } @Override public T getData(int index) { return mList.get(index); } @Override public void modify(T oldData, T newData) { modify(mList.indexOf(oldData), newData); } @Override public void modify(int index, T newData) { mList.set(index, newData); notifyDataSetChanged(); } @Override public boolean remove(T data) { boolean result = mList.remove(data); notifyDataSetChanged(); return result; } @Override public void remove(int index) { mList.remove(index); notifyDataSetChanged(); } }
当然这里还有好多的辅助类,这里就不在详解解释了,那最好我们怎么用呢?很简单,来一个之前的例子:
public class ParamRecycleAdapter extends BaseRecycleAdapter<ProductParamEntity> { public ParamRecycleAdapter(Context context, List<ProductParamEntity> list) { super(context, list, R.layout.item_product_param); } @Override protected void onBindData(BaseRecycleHolder viewHolder, int position, ProductParamEntity item) { viewHolder.setText(R.id.item_title, item.title) .setText(R.id.item_content, item.content); } }
我们只要注意上面标颜色的部分即可。我已经将这个封装为一个库文件,如果有需要的可以自己打包aar或者jar,相关资料请参照:打包aar,代码已经上传(文章最后)。
对于之前的Baseadapter这里也贴给大家:
public abstract class BasicAdapter<T> extends BaseAdapter { public Context mContext = null; protected LayoutInflater inflaterFactory = null; protected List<T> mList = new ArrayList<T>(); public BasicAdapter() { super(); } public BasicAdapter(Context context) { this.mContext = context; inflaterFactory = LayoutInflater.from(mContext); } public BasicAdapter(List<T> list) { if (list != null) { mList = list; } } public BasicAdapter(Context context, List<T> list) { this(context); this.mList = list; } public void setList(List<T> list) { if (list != null) { mList = list; notifyDataSetChanged(); } } public boolean addList(List<T> list) { if (list != null && list.size() > 0) { mList.addAll(list); notifyDataSetChanged(); return true; } return false; } public boolean add(T t) { if (t != null) { mList.add(t); notifyDataSetChanged(); return true; } return false; } public boolean add(int position, T t) { if (t != null && getCount() >= position) { mList.add(position, t); notifyDataSetChanged(); return true; } return false; } public void remove(T t) { if (mList.remove(t)) { notifyDataSetChanged(); } } public void remove(List<T> list) { if (mList.remove(list)) { notifyDataSetChanged(); } } public void remove(int index) { if (index >= 0 && index < mList.size()) { mList.remove(index); notifyDataSetChanged(); } } public void clear() { if (mList != null) { mList.clear(); notifyDataSetChanged(); } } public List<T> getList() { return mList; } @Override public int getCount() { if (mList != null && mList.size() > 0) { return mList.size(); } else return 0; } @Override public T getItem(int position) { if (mList!=null){ return mList.get(position); }else return null; } public T getLastItem() { if (mList.size() > 0) { return mList.get(mList.size() - 1); } return null; } @Override public long getItemId(int position) { return position; } public <V extends View> V inflate(int resource, ViewGroup root, boolean attachToRoot) { if (inflaterFactory == null) { inflaterFactory = LayoutInflater.from(mContext); } return (V) inflaterFactory.inflate(resource, root, attachToRoot); } public <V extends View> V inflate(int resource, ViewGroup root) { return inflate(resource, root, root != null); } public <V extends View> V inflate(int resource) { return inflate(resource, null, false); } }
最后贴上RecycleView.Adapter的封装库地址:点击打开链接
android RecycleView Adapter简单封装的更多相关文章
- Android ToolBar 的简单封装
使用过 ToolBar 的朋友肯定对其使用方法不陌生,由于其使用方法非常easy.假设对 ActionBar 使用比較熟练的人来说.ToolBar 就更easy了!只是,相信大家在使用的过程中都遇到过 ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
- Android -- OkHttp的简单使用和封装
1,昨天把okHttp仔细的看了一下,以前都是调用同事封装好了的网络框架,直接使用很容易,但自己封装却不是那么简单,还好,今天就来自我救赎一把,就和大家写写从最基础的OKHttp的简单get.post ...
- android代码优化----ListView中自定义adapter的封装(ListView的模板写法)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- [Android] Android RecycleView和ListView 自定义Adapter封装类
在网上查看了很多对应 Android RecycleView和ListView 自定义Adapter封装类 的文章,主要存在几个问题: 一).网上代码一大抄,复制来复制去,大部分都运行不起来,或者 格 ...
- Adapter的封装之路
原文:Adapter的封装之路 一.几种常见列表效果: 假如要用RecyclerView实现下面的几种效果,你会如何实现呢? 效果1:单布局效果 效果2:多布局效果 有多种Item布局 效果3 ...
- Android--Retrofit+RxJava的简单封装(三)
1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...
- 安卓控件RecycleView的简单使用
RecycleView的使用 目录 RecycleView的使用 技术概述 技术详述 遇到问题和解决 总结 参考文献 技术概述 RecycleView是谷歌官方对ListView的改进(并不是替代), ...
- Android之Adapter用法总结-(转)
Android之Adapter用法总结 1.概念 Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带.在常见的View(List View,Grid Vie ...
随机推荐
- 51nod 平均数(马拉松14)
平均数 alpq654321 (命题人) 基准时间限制:4 秒 空间限制:131072 KB 分值: 80 LYK有一个长度为n的序列a. 他最近在研究平均数. 他甚至想知道所有区间的平均数,但是 ...
- Codeforces Round #403 (Div. 1, based on Technocup 2017 Finals)
Div1单场我从来就没上过分,这场又剧毒,半天才打出B,C挂了好几次最后还FST了,回紫了. AC:AB Rank:340 Rating:2204-71->2133 Div2.B.The Mee ...
- Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined)
C题卡了好久,A掉C题之后看到自己已经排在好后面说实话有点绝望,最后又过了两题,总算稳住了. AC:ABCDE Rank:191 Rating:2156+37->2193 A.Oath of t ...
- bzoj 2783: [JLOI2012]树
Description 在这个问题中,给定一个值S和一棵树.在树的每个节点有一个正整数,问有多少条路径的节点总和达到S.路径中节点的深度必须是升序的.假设节点1是根节点,根的深度是0,它的儿子节点的深 ...
- Lucene——Field.Store(存储域选项)及Field.Index(索引选项)
Field.Store.YES或者NO(存储域选项) 设置为YES表示或把这个域中的内容完全存储到文件中,方便进行文本的还原 设置为NO表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完 ...
- Lock锁子类了解一下
前言 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 多线程基础必要知识点!看了学习多线程事半功倍 Java锁机制了解一下 AQS简简单单过一遍 只有光头才能变强! 上一篇已经将Loc ...
- CSS相关
===CSS框架=== https://github.com/lucasgruwez/waffle-grid 一个易于使用的 flexbox 栅格布局系统 ===CSS初始化=== https://g ...
- Node.js 工具模块
在 Node.js 模块库中有很多好用的模块.接下来我们为大家介绍几种常用模块的使用: 序号 模块名 & 描述 1 OS 模块 提供基本的系统操作函数. 2 Path 模块提供了处理和转换文件 ...
- 苹果OS系统安装Xcode方法
打开Xcode系统,在app store 里面找到自己系统对应的可升级的Xcode版本进行下载,下载到本地后,设置存放Xcode存放的文件夹为共享文件夹. 在MAC OS共享文件夹里面找到Xcode安 ...
- Docker 内核名字空间
Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多.当用 docker run 启动一个容器时,在后台 Docker 为容器创建了一个独立的名字空间和控制组集合. 名字空间提供了最基础 ...