如何为Recyclerview写一个通用的adapter
来源:互联网 发布:知思索的意思 编辑:程序博客网 时间:2024/09/21 09:28
如何写一个通用的RecyclerView.adapter
项目源码地址:https://github.com/jiang111/SuperRecyclerViewAdapter
欢迎star和fork
随着需求的不断修改,在项目中越来越流行使用recyclerview。
那么如何构建出一个通用的adapter来提高我们的快速开发能力。
下面我们就来看看如何构建出一个完善的baseadapter。
1.分析
想要构建出一个很nice的adapter,那你必须得熟悉recyclerview.adapter的执行流程,以及一些常用的方法吧。 通过分析,我们知道adapter中几个主要的方法。
*1. onCreateViewHolder() //用来创建一个viewholder(viewholder必须继承recyclerview.viewholder)
*2. onBindViewHolder() //用来根据当前item的位置进行数据绑定。
*3. getItemViewType() //返回你当前的adapter里有几种item
*4. getItemCount() //返回item的总个数
*5. 还有就是ViewHolder这个类 ,这个类主要用于拿到item中的相关控件
2.实战
既然 viewholder的作用主要是拿到item中相关控件, 那我们完全可以写一个通用的viewholder然后提供一个getview()的方法,让adapter去拿相应的view.进行设置值。
看代码
public class BaseViewHolder extends RecyclerView.ViewHolder { protected final SparseArray<View> mViews; protected View mConvertView; public BaseViewHolder(View itemView) { super(itemView); mViews = new SparseArray<>(); mConvertView = itemView; } /** * 通过控件的Id获取对应的控件,如果没有则加入mViews,则从item根控件中查找并保存到mViews中 * * @param viewId * @return */ public <T extends View> T getView(@IdRes int viewId) { View view = mViews.get(viewId); if (view == null) { view = mConvertView.findViewById(viewId); mViews.put(viewId, view); } return (T) view; } public View getmConvertView() { return mConvertView; }}
下面我们的adapter只需要使用BaseViewHolder,就可以了, 不需要在新建viewholder了。
public abstract class BaseAdapter<M> extends RecyclerView.Adapter<BaseViewHolder> { protected List<M> mLists; protected Context mContext; protected int layoutID; public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } private OnItemClickListener onItemClickListener; public BaseAdapter(List<M> mLists, Context mContext, int layoutID) { this.mLists = mLists; this.mContext = mContext; this.layoutID = layoutID; } public List<M> getmLists() { return mLists; } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { BaseViewHolder holder = new BaseViewHolder(LayoutInflater.from(mContext).inflate(layoutID, parent, false)); return holder; } @Override public void onBindViewHolder(BaseViewHolder holder, final int position) { if (onItemClickListener != null) { holder.getmConvertView().setClickable(true); holder.getmConvertView().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemClickListener.onItemClick(position); } }); } onBindView(holder, position); } protected abstract void onBindView(BaseViewHolder holder, int position); @Override public int getItemCount() { return mLists == null ? 0 : mLists.size(); }}
onCreateViewHolder方法我们以及写好了,只需要再暴露出onBindView这个抽象方法即可。
然后我们在我们的activity中。
mRecyclerView.setAdapter(new BaseAdapter<Character>(mLists, this, R.layout.item_main) { @Override protected void onBindView(BaseViewHolder holder, final int position) { TextView mTitle = holder.getView(R.id.item_tv); mTitle.setText(this.getmLists().get(position) + ""); } });
这样的adapter不包含head和foot的。
那我们再写一个包含head和foot的adapter
public abstract class BaseHeadFootAdapter<M> extends RecyclerView.Adapter<BaseViewHolder> { protected List<M> mLists; protected Context mContext; protected int layoutID; private boolean isHasHeader = false; private boolean isHasFooter = false; private int headerLayoutID; private int footerLayoutID; protected static final int TYPE_HEADER = -2; protected static final int TYPE_ITEM = -1; protected static final int TYPE_FOOTER = -3; public BaseHeadFootAdapter(List<M> mLists, Context mContext, int layoutID) { this.mLists = mLists; this.mContext = mContext; this.layoutID = layoutID; } public BaseHeadFootAdapter(int layoutID, Context mContext, List<M> mLists, int headerLayoutID, int footerLayoutID) { this.layoutID = layoutID; this.mContext = mContext; this.mLists = mLists; addHeader(headerLayoutID); addFooter(footerLayoutID); } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { BaseViewHolder holder; if (viewType == TYPE_HEADER) { if (headerLayoutID == 0) { throw new NullPointerException("header 资源ID尚未初始化"); } else { holder = new BaseViewHolder(LayoutInflater.from(mContext).inflate(headerLayoutID, parent, false)); } } else if (viewType == TYPE_FOOTER) { if (footerLayoutID == 0) { throw new NullPointerException("footer 资源ID尚未初始化"); } else { holder = new BaseViewHolder(LayoutInflater.from(mContext).inflate(footerLayoutID, parent, false)); } } else { holder = new BaseViewHolder(LayoutInflater.from(mContext).inflate(layoutID, parent, false)); } return holder; } @Override public void onBindViewHolder(BaseViewHolder holder, final int position) { if (isHasFooter) { if (isFooterPosition(position)) { onBindFooterView(holder, position); return; } } if (isHasHeader) { if (isHeaderPosition(position)) { onBindHeaderView(holder, position); return; } else { onBindView(holder, position - 1); } } else { onBindView(holder, position); } } protected abstract void onBindHeaderView(BaseViewHolder holder, int position); protected abstract void onBindFooterView(BaseViewHolder holder, int position); protected abstract void onBindView(BaseViewHolder holder, int position); public void addHeader(@LayoutRes int headLayoutID) { if (headLayoutID == 0) return; this.headerLayoutID = headLayoutID; isHasHeader = true; } public List<M> getmLists() { return mLists; } public void addFooter(@LayoutRes int footLayoutID) { if (footLayoutID == 0) return; this.footerLayoutID = footLayoutID; isHasFooter = true; } @Override public int getItemViewType(int position) { int viewType = TYPE_ITEM; if (isHasHeader) { if (isHeaderPosition(position)) { viewType = TYPE_HEADER; } } if (isHasFooter) { if (isFooterPosition(position)) { viewType = TYPE_FOOTER; } } return viewType; } protected boolean isFooterPosition(int position) { return position == getItemCount() - 1 ? true : false; } protected boolean isHeaderPosition(int position) { return position == 0 ? true : false; } @Override public int getItemCount() { int count = mLists == null ? 0 : mLists.size(); if (isHasFooter) { count++; } if (isHasHeader) { count++; } return count; }}
好了,这样我们通用的recyclerview的adapter就写好了。但是这样有个问题,如果我要想加载不同的布局,那怎么实现呢,显然BaseAdapter是不够用的,给大家一个思路, 如果要加载不同的布局,显然需要多个LayoutID和多个ViewType,既然他们都是int类型, 那完全可以把LayoutID作为adapter的ViewType来实现,然后在oncreateView的时候需要压入的layout直接拿viewType来使用就可以了。该思路实现的具体代码在 https://github.com/jiang111/SuperRecyclerViewAdapter
欢迎star和fork
- 如何为Recyclerview写一个通用的adapter
- 打造通用的Adapter为RecyclerView服务
- 为RecyclerView打造通用adapter
- 为RecyclerView打造通用Adapter
- 为RecyclerView打造通用Adapter
- android 写一个 通用的Adapter
- 不用再写RecyclerView的Adapter了,一个Adapter搞定
- 不用再写RecyclerView的Adapter了,一个Adapter搞定
- 为你的RecyclerView.Adapter添加通用DiffUtil适配器
- 通用的RecyclerView Adapter适配器
- 打造 RecyclerView的 通用Adapter
- 实现RecyclerView 的通用Adapter
- 通用的recyclerview adapter 适配
- 为RecyclerView打造通用Adapter 让RecyclerView更加好用
- 为RecyclerView打造通用Adapter 让RecyclerView更加好用
- 为RecyclerView打造通用Adapter 让RecyclerView更加好用
- 为RecyclerView打造通用Adapter 让RecyclerView更加好用
- 为RecyclerView打造通用Adapter 让RecyclerView更加好用
- 循环语句-JTable与 removeRow
- 开源项目源码解析
- UVA1593
- 小于等于符号无法由前台传递到后台脚本页面
- 关于dialog的一些小结
- 如何为Recyclerview写一个通用的adapter
- PLSQL Developer连接数据库(64位操作系统)
- jquery ajax POST 例子详解
- 逻辑回归、决策树和支持向量机的直观理解
- android控件获取屏幕坐标
- 满满的情怀!扎克伯格写给初生女儿的信(全文)
- 如何检测一个String是否为空
- 剑指offer:最小的K个数
- 杭电“计算机学院大学生程序设计竞赛(2015’11)”题解【1-3】