RecylerView 的使用频率现在也算做是很高了吧?使用起来的确是挺方便的,也容易实现一些比较好看的效果

一、一般步骤

一般的设计流程都是如下所示
首先是需要一个 JavaBean 来承载数据,包含的内容分别是标题还有内容

public class Data {private String title;private String content;public Data(String title, String content) {this.title = title;this.content = content;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}}

然后继承 RecyclerView.Adapter ,并实现几个固定方法

public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.MyViewHolder> {private List<Data> dataList;private LayoutInflater layoutInflater;public MyRecyclerAdapter(Context context, List<Data> dataList) {this.dataList = dataList;layoutInflater = LayoutInflater.from(context);}@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View itemView = layoutInflater.inflate(R.layout.item_left, parent, false);return new MyViewHolder(itemView);}@Overridepublic void onBindViewHolder(MyViewHolder holder, int position) {holder.tv_title.setText(dataList.get(position).getTitle());holder.tv_content.setText(dataList.get(position).getContent());}@Overridepublic int getItemCount() {return dataList.size();}class MyViewHolder extends RecyclerView.ViewHolder {private TextView tv_title;private TextView tv_content;MyViewHolder(View itemView) {super(itemView);tv_title = (TextView) itemView.findViewById(R.id.tv_title);tv_content = (TextView) itemView.findViewById(R.id.tv_content);}}}

使用到的布局文件

<?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="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/tv_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="left"android:textSize="15sp" /><TextViewandroid:id="@+id/tv_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="15sp" /><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:background="#abc" /></LinearLayout>

然后再来为 RecycleView 填充 Adapter

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycleView);recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));List<Data> dataList = new ArrayList<>();for (int i = 0; i < 40; i++) {Data data = new Data("叶应是叶", "我也不知道说什么好,我也不知道说什么好,我也不知道说什么好,我也不知道说什么好");dataList.add(data);}MyRecyclerAdapter adapter = new MyRecyclerAdapter(this, dataList);recyclerView.setAdapter(adapter);}
}

运行效果如下

这里写图片描述

使用多了会发现,其实 MyRecyclerAdapter 中几个需要实现的方法其实都是步骤都是类似的,如果每次都要来重复这样的步骤,那真的是在做无用的工作了

这里,来为 RecycleView 设计一个通用 Adapter,取代掉那些重复的步骤,让代码更加简洁

二、通用ViewHolder

首先,继承 RecyclerView.ViewHolder 实现一个通用的 ViewHolder
当中,使用 SparseArray 来存放 View 以减少 findViewById 的次数,SparseArray 比 HashMap 更省内存,在某些条件下性能会更好,不过只能存储 key 为 int 类型的数据,正好用来存放资源ID

因为列表项中一般都是使用 TextView 和 ImageView 两个控件,所以这里提供两个控件的操作方法。此外,为了监听列表项单击和双击事件,这里再来自定义一个接口 onItemCommonClickListener ,用于点击事件回调

public class CommonViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener {// SparseArray 比 HashMap 更省内存,在某些条件下性能更好,只能存储 key 为 int 类型的数据,// 用来存放 View 以减少 findViewById 的次数private SparseArray<View> viewSparseArray;private onItemCommonClickListener commonClickListener;public CommonViewHolder(View itemView) {super(itemView);itemView.setOnClickListener(this);itemView.setOnLongClickListener(this);viewSparseArray = new SparseArray<>();}/*** 根据 ID 来获取 View** @param viewId viewID* @param <T>    泛型* @return 将结果强转为 View 或 View 的子类型*/public <T extends View> T getView(int viewId) {// 先从缓存中找,找打的话则直接返回// 如果找不到则 findViewById ,再把结果存入缓存中View view = viewSparseArray.get(viewId);if (view == null) {view = itemView.findViewById(viewId);viewSparseArray.put(viewId, view);}return (T) view;}public CommonViewHolder setText(int viewId, CharSequence text) {TextView tv = getView(viewId);tv.setText(text);return this;}public CommonViewHolder setViewVisibility(int viewId, int visibility) {getView(viewId).setVisibility(visibility);return this;}public CommonViewHolder setImageResource(int viewId, int resourceId) {ImageView imageView = getView(viewId);imageView.setImageResource(resourceId);return this;}protected interface onItemCommonClickListener {void onItemClickListener(int position);void onItemLongClickListener(int position);}public void setCommonClickListener(onItemCommonClickListener commonClickListener) {this.commonClickListener = commonClickListener;}@Overridepublic void onClick(View v) {if (commonClickListener != null) {commonClickListener.onItemLongClickListener(getAdapterPosition());}}@Overridepublic boolean onLongClick(View v) {if (commonClickListener != null) {commonClickListener.onItemClickListener(getAdapterPosition());}return false;}
}

三、通用RecyclerAdapter

再来实现一个通用的 RecyclerView.Adapter
因为不知道要使用到的数据类型是哪一种,也为了更好的适配各种数据类型,所以这里需要用到泛型

当中,onBindViewHolder(CommonViewHolder holder, int position) 需要我们自己来操作,所以这里再来声明一个抽象方法 bindData(CommonViewHolder holder, T data) ,由子类来负责实现绑定操作

public abstract class CommonRecycleAdapter<T> extends RecyclerView.Adapter<CommonViewHolder> {protected LayoutInflater layoutInflater;protected List<T> dataList;protected int layoutId;public CommonRecycleAdapter(Context context, List<T> dataList, int layoutId) {this.layoutInflater = LayoutInflater.from(context);this.dataList = dataList;this.layoutId = layoutId;}@Overridepublic int getItemViewType(int position) {return super.getItemViewType(position);}@Overridepublic CommonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View itemView = layoutInflater.inflate(layoutId, parent, false);return new CommonViewHolder(itemView);}@Overridepublic void onBindViewHolder(CommonViewHolder holder, int position) {bindData(holder, dataList.get(position));}@Overridepublic int getItemCount() {return dataList.size();}abstract void bindData(CommonViewHolder holder, T data);}

这样,就有了一个实现了基本操作的通用 Adapter
这里再来看看如何使用它

四、使用通用 Adapter

需要先来继承 CommonRecycleAdapter ,只需要实现一个方法即可,看起来简洁多了吧
代码中声明了两个构造函数,根据是否需要用到点击事件监听来选择

public class MyAdapter extends CommonRecycleAdapter<Data> {private CommonViewHolder.onItemCommonClickListener commonClickListener;public MyAdapter(Context context, List<Data> dataList) {super(context, dataList, R.layout.item_left);}public MyAdapter(Context context, List<Data> dataList, CommonViewHolder.onItemCommonClickListener commonClickListener) {super(context, dataList, R.layout.item_left);this.commonClickListener = commonClickListener;}@Overridevoid bindData(CommonViewHolder holder, Data data) {holder.setText(R.id.tv_title, data.getTitle()).setText(R.id.tv_content, data.getContent()).setCommonClickListener(commonClickListener);}}

这里选择要监听点击事件

public class MainActivity extends AppCompatActivity implements CommonViewHolder.onItemCommonClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycleView);recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));List<Data> dataList = new ArrayList<>();for (int i = 0; i < 40; i++) {Data data = new Data("叶应是叶", "我也不知道说什么好,我也不知道说什么好,我也不知道说什么好,我也不知道说什么好");dataList.add(data);}//MyRecyclerAdapter adapter = new MyRecyclerAdapter(this, dataList);MyAdapter adapter = new MyAdapter(this, dataList, this);recyclerView.setAdapter(adapter);}@Overridepublic void onItemClickListener(int position) {Toast.makeText(this, "position:" + position, Toast.LENGTH_SHORT).show();}@Overridepublic void onItemLongClickListener(int position) {Toast.makeText(this, "position:" + position, Toast.LENGTH_SHORT).show();}}

运行效果

这里写图片描述

五、布局多样化

前面,CommonRecycleAdapter 已经可以为我们节省很多代码了,免去了一些重复性操作
这里,可以再来更进一步使 CommonRecycleAdapter 得以更加通用

举个例子,类似微信App的聊天界面那样,自己发送的信息和对方发送来的信息位置是一左一右的,也就是说,这个聊天列表使用了两个不同的布局文件
那么,可以也为 CommonRecycleAdapter 加入支持多布局的功能

为了标识数据的不同,在 Data 类中加入一个新的变量 location

/*** Created by 叶应是叶 on 2017/2/25.*/public class Data {private String title;private String content;private String location;public Data(String title, String content) {this.title = title;this.content = content;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}}

之前使用的布局中标题是靠左的,这里再定义一个布局,使标题靠右

<?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="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/tv_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="right"android:textSize="20sp" /><TextViewandroid:id="@+id/tv_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="20sp" /><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:background="#abc" /></LinearLayout>

然后,需要有一个方法来判断哪种数据类型需要使用哪种布局,所以再来定义一个接口,getLayoutId() 用于返会布局文件ID

public interface MultiTypeSupport<T> {int getLayoutId(T item, int position);}

修改 CommonRecycleAdapter
如果 multiTypeSupport 不为 null,意思就是要使用到不同的布局文件了,则调用 getLayoutId() 方法,将其返回值作为 ItemViewType

public abstract class CommonRecycleAdapter<T> extends RecyclerView.Adapter<CommonViewHolder> {protected LayoutInflater layoutInflater;protected List<T> dataList;protected int layoutId;protected MultiTypeSupport<T> multiTypeSupport;public CommonRecycleAdapter(Context context, List<T> dataList, int layoutId) {this.layoutInflater = LayoutInflater.from(context);this.dataList = dataList;this.layoutId = layoutId;}@Overridepublic int getItemViewType(int position) {if (multiTypeSupport != null) {return multiTypeSupport.getLayoutId(dataList.get(position), position);}return super.getItemViewType(position);}@Overridepublic CommonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {if (multiTypeSupport != null) {layoutId = viewType;}View itemView = layoutInflater.inflate(layoutId, parent, false);return new CommonViewHolder(itemView);}@Overridepublic void onBindViewHolder(CommonViewHolder holder, int position) {bindData(holder, dataList.get(position));}@Overridepublic int getItemCount() {return dataList.size();}abstract void bindData(CommonViewHolder holder, T data);}

修改 MyAdapter 类,实现 MultiTypeSupport 接口,根据 Data 对象的 location 字段的值,来决定返回哪个布局文件的ID

public class MyAdapter extends CommonRecycleAdapter<Data> implements MultiTypeSupport<Data> {private CommonViewHolder.onItemCommonClickListener commonClickListener;public MyAdapter(Context context, List<Data> dataList) {super(context, dataList, R.layout.item_left);}public MyAdapter(Context context, List<Data> dataList, CommonViewHolder.onItemCommonClickListener commonClickListener) {super(context, dataList, R.layout.item_left);this.commonClickListener = commonClickListener;this.multiTypeSupport = this;}@Overridevoid bindData(CommonViewHolder holder, Data data) {holder.setText(R.id.tv_title, data.getTitle()).setText(R.id.tv_content, data.getContent()).setCommonClickListener(commonClickListener);}@Overridepublic int getLayoutId(Data item, int position) {if (item.getLocation().equals("left")) {return R.layout.item_left;}return R.layout.item_right;}}

再来修改 Activity 中的代码

public class MainActivity extends AppCompatActivity implements CommonViewHolder.onItemCommonClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycleView);recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));List<Data> dataList = new ArrayList<>();boolean bool = false;for (int i = 0; i < 40; i++) {Data data = new Data("叶应是叶", "我也不知道说什么好,我也不知道说什么好,我也不知道说什么好,我也不知道说什么好");if (!bool) {data.setLocation("left");} else {data.setLocation("right");}bool = !bool;dataList.add(data);}//MyRecyclerAdapter adapter = new MyRecyclerAdapter(this, dataList);MyAdapter adapter = new MyAdapter(this, dataList, this);recyclerView.setAdapter(adapter);}@Overridepublic void onItemClickListener(int position) {Toast.makeText(this, "position:" + position, Toast.LENGTH_SHORT).show();}@Overridepublic void onItemLongClickListener(int position) {Toast.makeText(this, "position:" + position, Toast.LENGTH_SHORT).show();}}

运行效果如下

这里写图片描述

可以看到,每隔一行使用到的布局都不一样

这样一来,通用的 Adapter 也设计完成了,以后即使需要使用到很多种不同的数据类型,只要继承 CommonRecycleAdapter ,实现一个或两个方法,就可以搞定 Adapter 了

这里提供示例代码下载:Android RecyclerView设计通用Adapter

Android RecyclerView设计通用Adapter相关推荐

  1. Android RecyclerView简单通用适配器

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

  2. android开源系统brvah,Android Jetpack之通用Adapter(Databinding+BRVAH)

    之前发过一个databinding版的通用adapter,能实现一般需求,不过功能比较简陋,实际开发中大家更倾向于使用BRVAH等功能丰富的第三方框架.现在给出一个基于BRVAH的databindin ...

  3. Android: RecyclerView.ViewHolder、Adapter

    1.简介  用户滑动屏幕切换视图时,上一个视图会回收利用,RecyclerView所做的就是回收再利用,循环往复. ViewHolder  ViewHolder的主要任务:容纳View视图. Adap ...

  4. Android Studio类微信界面之RecyclerView设计

    目录 一.RecyclerView基本概念 二.前端页面设计 item_dome.xml tab01.xml 三.后端代码 VerticalAdapter.java weixinfragment.ja ...

  5. Android中适用于ListView、GridView等组件的通用Adapter

    今天随便逛逛CSDN,看到主页上推荐了一篇文章Android 高速开发系列 打造万能的ListView GridView 适配器,刚好这两天写项目自己也封装了相似的CommonAdapter,曾经也在 ...

  6. Android RecyclerView(五)封装Holder与Adapter(Android 5.0 新特性)

    Android RecyclerView(五)封装Holder与Adapter(Android 5.0 新特性) 1 效果 2 BaseHolder的封装 public class BaseViewH ...

  7. Android UI设计之十一自定义ViewGroup,打造通用的关闭键盘小控件ImeObser

    2019独角兽企业重金招聘Python工程师标准>>> 转载请注明出处:http://blog.csdn.net/llew2011/article/details/51598682 ...

  8. Android RecyclerView 通用Adapte,单一类型

    项目中使用的通用Adapter 和ViewHolder ,这两个只支持单一ItemType CommonAdapter public abstract class CommonAdapter<T ...

  9. Android:打造“万能”Adapter与ViewHolder

    ##写在前面 最近一直忙着各种结课大作业,重新看起Android还有种亲切感.前段时间写项目的时候,学习了一个万能Adapter与ViewHolder的写法.说是"万能"其实就是在 ...

最新文章

  1. MySQL · 引擎介绍 · Sphinx源码剖析(三)
  2. Hugging Face官方NLP课程来了!Transformers库维护者之一授课,完全免费
  3. Neuron最新研究:神经科学家测量球迷大脑对比赛的反应,试图挖掘人类的深层天性...
  4. C 语言的标准输入对象是,《面向对象程序设计C+》期末试卷及标准答案
  5. maven中net.sf.json报错的解决方法
  6. SQL SERVER “扩展属性的应用
  7. php 伸展菜单代码,上下伸展的JS菜单
  8. 广播接收器动态静态注册
  9. SQL:postgresql增加自增字段
  10. JAVA线程池shutdown和shutdownNow的区别
  11. 常用的英文单词2000
  12. 利用Python处理Excel数据
  13. java实现pdf黑白化 : pdf转图片、图片黑白化、图片转pdf
  14. RobotStudio软件:ABB机器人喷涂虚拟仿真
  15. 集算器替代存储过程实现报表数据源
  16. 打散线条lisp_cad细线模式(cad中宽线炸开后变成细线是怎么回事)
  17. ROS1云课→18一键配置
  18. 解读2018:13家开源框架谁能统一流计算?
  19. Flink On K8s
  20. 用计算机弹出生僻字的歌,抖音生僻字是什么歌?抖音生僻字歌词注音完整版

热门文章

  1. BJUI接受TabID实现添加或编辑后自动刷新页面
  2. BJUI修改详情页的标题内容
  3. 9、mybatis自增主键策略
  4. map中只有一个值 获取_小学数学,为什么一个三角形中最多只有一个直角或一个钝角...
  5. gsea富集分析结果怎么看_怎么看肝功能检验结果?
  6. 精灵混合加密系统_数据安全——混合云的数据备份
  7. crc可以检出奇数个错误_计算机网络最新章节_陈虹著_掌阅小说网
  8. 再见,汉斯·罗斯林,你用数据让宏大的问题变有趣 | 好奇心小数据
  9. minimum-depth-of-binary-tree (搜索)
  10. InputStream 、 InputStreamReader 、 BufferedReader区别