深入:封装最简单的RecyclerView——Adapter
深入:封装最简单的RecyclerView——Adapter
RecyclerView通常Adapter
Google在Android5.0推出新控件RecyclerView,优化了ListView的各种不足,本篇就是《深入:打造最简单的ListView---Adapter》的续篇!没有看过的小伙伴赶紧查看历史文章或者撮链接:
https://mp.weixin.qq.com/s?__biz=MzIzNTc4MTQ1MA==&mid=2247483667&idx=1&sn=2d5fab189001bc1069b748a22b2f00d4&chksm=e8e0ad36df9724208b75c6ad793ee3cdfde7d011a910bf38eff9244bb61dd8e20d2b0980ec28#rd
通常实现RecyclerView一样需要实现setAdapter方法,通常做法是新建一个Adapter继承RecyclerView.Adapter重写其中数个方法,相信你早已熟知其基本用法。
实际开发中由于会用到不止一个RecyclerView,不断重复以上步奏使得代码臃肿,实现起来非常费劲。
Adapter初步封装
一样的步奏,我们先写Adapter:
1.创建自己的JoshuaAdapter继承RecyclerView.Adapter,泛型定义为我们内部的ViewHodler。
2.创建数据源集合,存储整个RecyclerView的item数据,由于数据类型未知,定义泛型Data。
3.创建内部类ViewHodler继承至RecyclerView.ViewHolder。
图上,是相应的代码实现与详细的注释,值得注意的是:其一:我们并没有在ViewHolder构造方法中初始化控件,因为此处属于封装的基类,item布局是未知的。其二:我们在ViewHolder内部创建了bind方法(绑定item数据),其内部实现是调用抽象方法onBind由子类实现操作。
ViewHodler暂时写到这。JoshuaAdapter需要补充一个带形参的构造方法,传入数据源List。我们接着实现onCreateViewHolder:
如上图,我们把引入item布局的操作和创建实例化ViewHolder对象的操作全部都交给CreateItemView和CreateHolder两个抽象方法去实现,基类并不想涉及这些。接下来是onBindViewHolder方法:
在onBindViewHolder中我们调用了之前ViewHolder类创建的bind方法,这么封装的目的是为了不在基类去绑定item数据,我们把当前item的数据data与holder都最终抛给抽象的onBind方法,由子类统一实现。
Adapter再封装
都Adapter初步封装中,我们完成了Adapter最基础的业务封装,把ViewHolder的初始化控件操作放到了子类去实现,把onCreateViewHolder的操作同样抛给了子类去实现,以及onBindViewHolder绑定数据的操作放到了ViewHolder最终还是上抛子类去实现。总感觉还差点什么?是的,我们应该给子类提供一个更新某条item数据的方法!
如上图,我们另外创建了一个AdapterCallback.java接口,泛型Data依然是我们的item的数据类型,接口提供更新数据的方法update,那么问题来了,更新某条item数据我们需要什么条件呢?
1.将要更新的Data数据。
2.当前item的ViewHolder对象,有了hodler,item下标就可以拿到。所以我们的接口必须携带这俩参数。
相信你在前面的图片中你一定看到了许多红色的圈圈,到这里可就不能暂时不管啦!滑到第二张开始,我们发现在JoshuaAdapter早已实现了AdapterCallback接口:
在重写的update方法中,我们的职责就是替换目标下的数据Data,然后更新界面。那么问题来了,有接口就会有回调,谁回调了update方法呢?是ViewHolder,我们的内部类ViewHolder是未完待续的!
在ViewHolder中我们添加了updateDate方法用于触发update回调,callback便是在第二张代码图片圈出的AdapterCallback callback。在这里我们进行了简单的判空,那么callback在哪里被赋值?在onCreateViewHolder方法中便holder.callback=this;注入回调了(每一个item的holder对象callback都不会为空)。在相应的代码图片上已经圈出。这样外部通过holder调用updateDate方法传入需要更新的数据便可方便的实现更新目标数据。
我们知道RecyclerView摒弃了子项点击事件的监听器,所有的点击事件都是由具体的View去注册,在JoshuaAdapter中我们就注册了监听器,但是我们在Click事件中转发了点击事件,转发过程中我们通过Click方法中的View拿到对应的ViewHolder,通过holder获取对应item的下标从而在我们自定义的onItemClick接口中回调。这样实现类便可方便的获取点击对应的item所有的引用资源。下图是实现代码:
Adapter打造完成
封装了这么久的Adapter总该试下好不好用对吧!我们来到MainActivity:
图上的代码很简单,我们的数据源是小机器人图片的资源ID,关键类是Radapter,我们看看其实现:
图上的Radpter类继承了我们前面封装的JoshuaAdapter,非常简单清晰的实现了适配器的业务逻辑,我们只需要关心item的布局引入,hodler的创建,还有点击事件的处理就好了。
关于holder的创建就更简单了,直接继承我们的JoshuaAdapter.ViewHolder,只需要关心在构造函数中初始化控件,在onBind方法中set数据便完成了。
Adapter值得改进的地方
如果RecyclerView包含多种item类型,那么上面的Adapter封装也许就需要改动了:
JoshuaAdapter.onCreateViewHolder中的CreateItemView方法应该换成图上,使用viewType作为inflate方法中的layout资源ID,CreateHolder也应该新增viewType参数。
JoshuaAdapter中需要重写getItemViewType方法,通常的做法是在此方法中根据position判断此item类型,并返回标识,然后在onCreateViewHolder中根据参数viewType分别引入不同的layout。但是我们这里直接把layout资源ID返回,更加方便迅速。
最后在Adapter的子类中实现getItemViewType方法,由于参数中已经携带Data数据,可以根据item数据判断将对应的layout资源ID返回便可.
至此我们完成了RecyclerView的封装,放到项目Module中,在任何地方都可以方便的调用。谢谢阅读
备注:本文学习来源自慕课网实战课程《带后台的IM即时通讯App 全程MVP手把手打造》
http://coding.imooc.com/class/100.html
欢迎长按下图-识别图中二维码或者扫一扫,搜索微信公众号:黄君华。关注我的公众号:
如果你有不同意见或建议或者有好的技术文章想和大家分享欢迎投稿,可以把你的文章使用附件的形式发送到我的邮箱2908116133@qq.com
谢谢阅读!