一直都想写一个通用的RecyclerView适配器,但是一直都无从下手,后来看了鸿洋大神的博客后才知道怎么写,并且在此基础上添加了点自己的东西,终于算是大功告成。先上代码看看

public class ViewHolder extends RecyclerView.ViewHolder {private Context context;private SparseArray<View> mViews;private View mConvertView;public ViewHolder(Context context, View itemView, ViewGroup parent) {super(itemView);this.context=context;this.mConvertView=itemView;mViews=new SparseArray<>();}//获得holder对象public static ViewHolder getHolder(Context context,ViewGroup parent,int layoutId){View itemView= LayoutInflater.from(context).inflate(layoutId,parent,false);ViewHolder holder=new ViewHolder(context,itemView,parent);return holder;}//通过id获取控件public <T extends View> T getView(int viewId){View view=mViews.get(viewId);if (view==null){view=mConvertView.findViewById(viewId);mViews.put(viewId,view);}return (T)view;}/******************************以下是辅助方法******************************///设置文字的方法public ViewHolder setTexts(int viewId,String text){TextView tv=getView(viewId);tv.setText(text);return this;}//设置图片的方法public ViewHolder setImage(int viewId,int resId){ImageView iv=getView(viewId);iv.setImageResource(resId);return this;}//设置点击事件public ViewHolder setClickListener(int viewId, View.OnClickListener listener){View view=getView(viewId);view.setOnClickListener(listener);return this;}}

这是一个通用Viewholder,大家可以看到代码很简单,包括构造函数总共也就三个函数而已其他两个分别是getHolder(获得holder对象的方法)和getView(通过id获得view的方法),在这个通用holder中定义了三个变量,其中SparseArray是用来存放View的,这个东西可有可无,用了比不用更有效率,不用的话这样写就好了(getView方法中):View view=mConvertView.findViewById(viewId); return (T)view;,其他两个也没什么异议的了,相信大家都懂的。以上这些就是通用ViewHolder主要的部分了。至于后面的三个辅助方法则是为了更方便的设置图片文字等,大家有需要的可以自行加上去即可。接下来我们说说getView方法,这个方法就是我们找到item里的控件的方法,大家可以看到,我们只需要将控件的id传入即可。看的不是很明白的同学可以点开我上面链接的鸿洋大神的博客来看。
ViewHolder先到这里,现在看看RecyclerView的Adapter。

public abstract class CommentAdapter<T> extends RecyclerView.Adapter<ViewHolder> {protected Context mContext;protected int mLayoutId;protected List<T> mDatas;protected LayoutInflater mInflater;/**********设置FooterView和HeaderView********************/private static final int TYPE_NORMAL = 0;private static final int TYPE_FOOTER = 1;private static final int TYPE_HEADER = 2;private int headerViewId = 0;private int footerViewId = 0;public void setFooterView(int footerViewId) {this.footerViewId = footerViewId;notifyItemInserted(getItemCount() - 1);}public int getFooterView() {return footerViewId;}public void setHeaderView(int headerViewId) {this.headerViewId = headerViewId;notifyItemInserted(0);}public int getHeaderViewId() {return headerViewId;}/**********************  Item点击接口  *********************/public interface OnItemClickListener {void onItemClick(View view, int position);}private OnItemClickListener onItemClickListener;//设置item点击时间监听的方法public void setOnItemClickLitener(OnItemClickListener onItemClickListener) {this.onItemClickListener = onItemClickListener;}/************************构造器****************************/public CommentAdapter(Context context, int layoutId, List<T> datas) {mContext = context;mInflater = LayoutInflater.from(context);mLayoutId = layoutId;mDatas = datas;}/***************加载更多数据方法**************/public void onLoadMoreDatas(List<T> datas) {if (mDatas == null) {mDatas = datas;notifyDataSetChanged();} else {mDatas.addAll(datas);notifyDataSetChanged();}}@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {if (headerViewId != 0 && viewType == TYPE_HEADER) {    return ViewHolder.getHolder(mContext, parent, headerViewId);} else if (footerViewId != 0 && viewType == TYPE_FOOTER) {    //假如footerViewId不等于0和viewType等于TYPE_FOOTER则返回footerViewreturn ViewHolder.getHolder(mContext, parent, footerViewId);}ViewHolder viewHolder = ViewHolder.getHolder(mContext, parent, mLayoutId);return viewHolder;}@Overridepublic void onBindViewHolder(final ViewHolder holder, int position) {final int pos = holder.getLayoutPosition();//获得item的位置if (getItemViewType(pos) == TYPE_HEADER) {convert(holder, null, position, false, true);} else if (getItemViewType(pos) == TYPE_FOOTER) {convert(holder, null, position, true, false);} else {if (getHeaderViewId() != 0) {convert(holder, mDatas.get(position - 1), position, false, false);} else {convert(holder, mDatas.get(position), position, false, false);}}if (onItemClickListener != null) {holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {onItemClickListener.onItemClick(holder.itemView, pos);}});}}@Overridepublic int getItemViewType(int position) {if (footerViewId == 0 && headerViewId == 0) return TYPE_NORMAL;if (headerViewId != 0) {if (position == 0) {return TYPE_HEADER;}}if (footerViewId != 0) {if (position == getItemCount() - 1)return TYPE_FOOTER;}return TYPE_NORMAL;}@Overridepublic int getItemCount() {if (footerViewId != 0 && headerViewId != 0) {return mDatas.size() + 2;} else if (footerViewId != 0 && headerViewId == 0) {return mDatas.size() + 1;} else if (footerViewId == 0 && headerViewId != 0) {return mDatas.size() + 1;}return mDatas.size();}public abstract void convert(ViewHolder holder, T t, int position, boolean isFooter, boolean isHeader);
}

大家可以看到,我这个通用Adapter中提供了插入Header和Footer的方法和Item点击的方法,插入Footer和Header方法也只需要提供布局id即可,关于这个插入footer和header,最主要的是判断返回item数目,相信大家都可以看的懂的。其他的我就不说那么多了,主要就是通过泛型接收数据并设置上去,加载更多数据方法也是,接收要添加的数据并通知更新即可,在这里有个点要提醒大家,有人说Recyclerview使用notifyDataSetChanged()不如直接使用Listview,对此我并不是很懂是为什么,反正我只会用notifyDataSetChanged()来通知更新批量数据。还有很多不完善的地方,我这里只是提供个例子供大家参考,不喜勿喷。最后贴一下调用适配器的例子,

public class Test extends Activity {//这里是找id,没用过这个框架的同学用传统的方法即可@BindView(R.id.rv_test)RecyclerView mTest;@BindView(R.id.bt_addHeader)Button mAddHeader;@BindView(R.id.bt_addFooter)Button mAddFooter;@BindView(R.id.bt_addDatas)Button mAddDatas;TextView loadMore;ProgressBar pb;TextView loadMore2;ProgressBar pb2;CommentAdapter<String> commentAdatper = null;private List<String> datas = new ArrayList<>();@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);View view = View.inflate(Test.this, R.layout.activity_mvc, null);ButterKnife.bind(Test.this, view);setContentView(view);init();}private void init() {addDatas();initListener();mTest.setLayoutManager(new LinearLayoutManager(this));mTest.setAdapter(commentAdatper = new CommentAdapter<String>(Test.this, R.layout.item_test, datas) {@Overridepublic void convert(final ViewHolder holder, final String s, final int position, boolean isFooter, boolean isHeader) {if (isHeader) {loadMore2 = holder.getView(R.id.tv_loadMore);pb2 = holder.getView(R.id.pb_loading);} else if (isFooter && position == commentAdatper.getItemCount() - 1) {loadMore = holder.getView(R.id.tv_loadMore);pb = holder.getView(R.id.pb_loading);} else {holder.setTexts(R.id.tv_test, position + s);}}});mTest.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));commentAdatper.setOnItemClickLitener(new CommentAdapter.OnItemClickListener() {@Overridepublic void onItemClick(View view, int position) {Toast.makeText(Test.this, "点击了" + position + "项", Toast.LENGTH_SHORT).show();if (commentAdatper.getHeaderViewId() != 0 && position == 0) {loadMore2.setVisibility(View.GONE);pb2.setVisibility(View.VISIBLE);}if (commentAdatper.getFooterView() != 0 && position == commentAdatper.getItemCount() - 1) {loadMore.setVisibility(View.GONE);pb.setVisibility(View.VISIBLE);}}});}private void initListener() {mAddHeader.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {commentAdatper.setHeaderView(R.layout.item_footerview);}});mAddFooter.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {commentAdatper.setFooterView(R.layout.item_footerview);}});mAddDatas.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {commentAdatper.onRefreshDatas(newDatas());}});}private void addDatas() {datas.add("123");datas.add("是领导看看菲拉斯");datas.add("我我我");datas.add("lsjd");datas.add("sdf");datas.add("fgj");datas.add("rty");datas.add("jh,");datas.add("123");datas.add("是领导看看菲拉斯");datas.add("我我我");datas.add("lsjd");datas.add("sdf");datas.add("fgj");datas.add("rty");datas.add("jh,");datas.add("123");}private List<String> newDatas() {List<String> datas = new ArrayList<>();datas.add("东东");datas.add("南南");datas.add("西西");datas.add("北北");return datas;}}

最后是对应的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Button
            android:id="@+id/bt_addHeader"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="添加Header"/><Button
            android:id="@+id/bt_addFooter"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="30dp"android:text="添加Footer"/><Button
            android:id="@+id/bt_addDatas"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="30dp"android:text="添加Datas"/></LinearLayout><android.support.v7.widget.RecyclerView
        android:id="@+id/rv_test"android:layout_width="match_parent"android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView></LinearLayout>

item的布局文件大家可以自行写,这里就不贴了。我写的通用适配器有很多不完善的地方,希望能给大家提供个参考,不懂的地方可以在下面留言,我一定全力解答。我旨在提供个例子,让有需要的人参考。希望大家能够共同进步,共同学习,祝早日走上人生巅峰。

Android RecyclerView简单通用适配器相关推荐

  1. Android RecyclerView设计通用Adapter

    RecylerView 的使用频率现在也算做是很高了吧?使用起来的确是挺方便的,也容易实现一些比较好看的效果 一.一般步骤 一般的设计流程都是如下所示 首先是需要一个 JavaBean 来承载数据,包 ...

  2. kotlin中RecyclerView.Adapter通用适配器

    文章目录 结合databinding,livedata BaseViewHolder BaseAdapter recycleView通用adapter 使用 数据bean ViewModel 绑定it ...

  3. 一个适用于ListView/GridView/RecyclerView的通用适配器

    简化大量重复代码 支持多布局 自定义图片加载 常用数据操作 view复用 RecyclerView item 点击和长按事件 GitHub源码地址 简书地址 gradle依赖 dependencies ...

  4. android RecyclerView 简单实现横竖布局穿插

    关于RecyclerView 就不多说 ,鸿翔大神已经写的非常详细了. 先上图,主要实现效果(又有水平布局,又有垂直布局): 直接上关键代码: RecyclerView recyclerView = ...

  5. Android适配器以及作用,Android RecyclerView 通用适配器的实现

    分析 我们需要在RecyclerViewAdapter内部维持一个数据集合的引用 需要实现Item的点击事件,包括短按和长按,并需要向外部提供设置监听器的方法 这个适配器必须通用,所以应该是泛型的,并 ...

  6. android怎么设置适配器,Android之自定义实现BaseAdapter(通用适配器三)

    在上一篇中,我们说过,在setData中如果有很多控件的话,我们还是要在该方法中写入很多代码,为了降低开发的方便性,本次就在此基础上再一次优化.实现原理是这样的,每次在setData中都要查找控件,然 ...

  7. Android 控件 RecyclerView简单使用

    Android 控件 RecyclerView简单使用 1.导依赖库 implementation 'com.android.support:recyclerview-v7:27.1.1'implem ...

  8. 【Android开发】自定义ListView,使用通用适配器,并实现ListView上的每一项和每一项上的按钮等控件同时监听

    ListView在Android开发中是比较常用的系统组件,但是有时候我们除了需要做ListView上每一行的点击监听事件之外,如果每一行上还有其他需要监听的控件例如Button.CheckBox等, ...

  9. android中适配器,android:打造万能通用适配器

    本文原创,转载请注明出处. 1.前言 listview作为安卓项目中一个的明星控件,它的适配器的写法是广大安卓开发者需要掌握和优化的技巧. 本文旨在介绍一个通用的适配器BaseCommAdapter写 ...

最新文章

  1. 360浏览器调用selenium
  2. 使用Python可视化卷积神经网络方法汇总
  3. Tomcat中web.xml文件的详细说明
  4. 网易数据中台建设实践
  5. AS(Android studio)常见问题
  6. C#获取txt记事本内容,防止乱码情况
  7. thief book怎么用_战略管理工具箱--30个好用的战略管理好工具
  8. 《Hadoop海量数据处理:技术详解与项目实战(第2版)》一第2章 环境准备
  9. hello March
  10. linux自学笔记--DNS服务器
  11. 使用Spring Data JPA作为持久层框架
  12. 【蓝桥杯Java组】一学就会的小技巧(五):矩阵快速幂
  13. “逆鬼”muma企图隐蔽发展 被360独家击杀
  14. 西工大计算机学院优秀毕业生,计算机学院优秀博士毕业生陈穆林:不负时光 不负自己 奋斗的时光是一抹永不褪色记忆...
  15. 淘宝旺旺号转userid 或 uid 接口与方法
  16. UVa - 11283 - PLAYING BOGGLE
  17. Android 关于佳博和汉印蓝牙热敏打印机开发,kotlin爬虫app
  18. html字体铺盖颜色,这5种颜色的褥子不要去买,盖上会让你的家财散尽!
  19. linux用户和组管理的实验报告,linux用户管理任务实验报告
  20. 这可能是全网最详细的 Python 安装教程(windows)

热门文章

  1. 我们用最详细的方式解析Android消息机制的源码,小白也能看明白
  2. 施工方不按设计图纸施工,承担哪些责任
  3. 华为:hybrid配置及原理,实现不同vlan访问服务器。
  4. 斐讯phicomm原厂固件桥接AP设置图文教程
  5. UDP实现高并发其实非常简单(续集)
  6. 讯飞错误码10116
  7. v42.05 鸿蒙内核源码分析(中断切换) | 系统因中断活力四射 | 百篇博客分析鸿蒙源码
  8. <Halcon>分割粘连区域(分水岭算法)
  9. hp6531s闪屏门 6531s闪屏
  10. SugarCRM源码分析之数据库连接