Android(安卓)RecyclerView —— 适配器封装探索
Android RecyclerView —— 适配器封装探索
Android RecyclerView —— 基本使用
Android RecyclerView —— 自定义分割线
RecyclerView
适配器的编写
RecyclerView
如果需要填充数据,就必须使用到适配器。在一般情况下,我们定义一个适配器只需要定义一个类,然后集成 RecyclerView.Adapter
类,然后实现齐总的抽象的方法即可,如下,实现一个简单的适配器:
public class MyAdapter extends RecyclerView.Adapter { private List dataList = new ArrayList<>(); @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { return new MyViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout,false)); } @Override public void onBindViewHolder(@NonNull MyViewHolder viewHolder, int i) { viewHolder.setData(dataList.get(i)); } @Override public int getItemCount() { return dataList.size(); } static class MyViewHolder extends RecyclerView.ViewHolder { public MyViewHolder(@NonNull View itemView) { super(itemView); } } public void setData(String itemData){ // 设置数据 }}
实现起来是比较简单的,代码量也不算太多,但是一个应用里面往往会有大量的列表,如果我们一个一个的都如此实现,就会有大量的重复代码。那么,对Adapter进行封装就很有必要了。
RecyclerView
适配器封装方式探索
对代码的封装有多种方式,那么,对RecyclerView
适配器的封装同样也有很多的方式。在这里,主要说一下两种封装方式:
1.抽取基类
思路:将多个 Adapter
中相同的代码抽取成基类,并且相关的事件(item 单击、长按等) 也封装到基类中,将不同的地方定义为抽象,由具体的子类来实现。这种方式是最容易想到的,同时也是比较常见的封装形式
思路解析:通过上的封装方式我们发现,每一个列表都需要绑定一个对应的 Adapter
类,然后创建一个或多个 RecyclerView.ViewHolder
类(一般为静态内部类)区分不同的 item 类型,这样虽然在一定程度上减少的代码量,不过有几个坏处:
① 我如果在后期需要在列表中增加一种item样式,那么就需要修改对应的
Adapter
类,新建一个内部RecyclerView.ViewHolder
类,并在Adapter
的onCreateViewHolder()
方法中返回以及onBindViewHolder()
方法中判断以及设置具体数据。显然这种方式是不太友好的,因为他会修改我们以前的代码,尤其是当Adapter
类的代码比较多时,更难修改并且更加容易出错;
② 因为在创建RecyclerView.ViewHolder
类时,一般都是使用的内部类的形式,那么当应用中不同的列表中有多个完全一样的item类型时(他们属于不同的RecyclerView
,或者是多个RecyclerView
都有不同的 item 类型,但是他们有部分 item 是完全一样的),那么也会直接在不同的Adapter
中的创建多个相同的RecyclerView.ViewHolder
内部类,这样导致相同的代码编写了多遍,而修改时,也需要修改多个类,增加量遗漏和发生错误的可能。
其实上面的两个问题也可以简单的归纳为两个字:耦合,每一个列表和对应的 Adapter
耦合在一起了,然后 Adapter
又和他下面的每一个 item 耦合在一起了,所以导致了问题的发生。
2.基于上面的两个问题,所以第二种方式主要就是对列表和 Adapter
以及 item 之间进行解耦
思路:首先我们看一下RecyclerView
怎样显示list集合数据的,要将一个的数据填充到RecyclerView
中,需要借助一个类,那就是 RecyclerView.Adapter
类,RecyclerView.Adapter
类中包含了具体列表的具体数据,每一条数据就是一个 item,那么可以用下图表示他们之间的关系:
通过图可以得知,其实 RecyclerView
只是要借助 RecyclerView.Adapter
类填充数据,而 RecyclerView.Adapter
和 item 之间的也没有必然联系,只是有包含关系,那么我们就可以使用如下的方式来进行解耦,如图:
思路解析:把Adapter
剥离,将item作为一个最小单元添加到Adapter
中,然后RecyclerView
通过持有Adapter
的对象来显示item数据。这样一来,当需要新的不同类型的item时,只需要新建一个item单元,然后调用Adapter
的方法将item增加到Adapter
中即可,而不需要修改Adapter
的代码,同时,因为是将item作为一个单元,那么,应用中有相同的item类型时,也是可以共用的。
使用代码实现
抽取基类的方式有网上有很多写的非常好的文章和代码了,这了就不再使用代码来实现了。主要看看第二种解耦的代码实现。 可以直接进入 GitHub 下载代码
步骤说明:
首先,我们把每个item单元作为一个cell来看,定义一个接口 IRecyclerCell
并定义基本方法,然后提供一个默认的实现 abstract class RecyclerCell
。
其次,定义一个统一的 Adapter
类,RecyclerAdapter
,他主要包含了对 item 单元 IRecyclerCell
的增删改等操作并刷新列表。
接着,因为 RecyclerView.Adapter
类的 onCreateViewHolder()
方法需要返回一个 RecyclerView.ViewHolder
,所以我们封装一个统一的 ViewHolder叫做 RecyclerViewHolder
,在这个类中使用 SparseArray
来保存item的字View,减少 findViewById()
操作,并提供对常见 view 的值进行设置、getView()
、item的单击事件、长按事件等监听。
最后,就是将这几个类关联起来。我们说了,这种方式主要是进行解耦,把每一个item作为一个cell来处理,所以我们应该对不同的item,来创建不同的 cell(当然新建的cell需要继承 RecyclerCell
,泛型表示该item的数据),现实其抽象方法,然后在页面中根据数据创建不同 cell 对象,添加到列表中,最后将cell对象列表设置到统一的Adapter
—— RecyclerAdapter
中就能实现数据的填充了。
下面三个方法是 RecyclerCell
实现类必须实现的方法:
getRecyclerItemType()
方法很重要,尤其是对于一个列表中有多种item类型时,他的返回值就是用来区分不同item类型的标记,如果返回值一样,那表示item的类型一样,不同的列表中互不干扰
onCreateViewHolder()
方法返回一个统一的 RecyclerViewHolder
onBindViewHolder()
方法绑定 holder
/** * 返回 item 类型,子类必须实现。并且添加到同一个 {@link RecyclerAdapter} 的不同 * {@link IRecyclerCell} 的 {@link #getRecyclerItemType()} 返回值必须不同
* 作用:用于在 {@link RecyclerAdapter} 中区分不同的 item 类型。 * * @return item 类型值,用于区分不同的 item 类型 */int getRecyclerItemType();T getItemData();/** * 创建 ViewHolder * * @param viewType 正常情况下该参数的值和 {@link #getRecyclerItemType()} 方法的返回值相等 */@NonNullRecyclerViewHolder onCreateViewHolder(@NonNull Context context, @NonNull ViewGroup parent, int viewType);/** * 绑定 holder,{@link RecyclerCell#itemData} 为 item 数据 */void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position, T itemData);
去 GitHub 下载代码
更多相关文章
- 解析android中的帮助、about、关于作者、HELP等提示页面
- Android(安卓)Material Design Snackbar Example
- Android(安卓)JNI实例代码(二)
- android 动态加载布局文件三种方法
- 《Android(安卓)JNI》05 在JNI中调用Java的函数
- Android(安卓)SQLiteOpenHelper
- Android(安卓)判断手机是否安装某个应用
- 安卓新技术学习资料整理 常更新哦~
- Android悬浮通知无效的问题