背景
一转眼,从一开始发布文章说带大家
封装Adapter
直到现在,过去半个月了吧,前后又仔细阅读了很多Adapter的框架源码,对Adapter的千变万化算是有了深刻的认识,真的是温故而知新,借着这次机会,我也将学到的这些优点一一的列出来告诉你,跟我一起重新认识Adapter
值得一看的Adapter开源项目
- mikepenz/FastAdapter
- DevAhamed/MultiViewAdapter
- davideas/FlexibleAdapter
- sockeqwe/AdapterDelegates
- liangjingkanji/BRV
- evant/binding-collection-adapter
- nitrico/LastAdapter
- 作者Adapter
这些开源项目都有哪些相同点?
- 这几个项目最大的共同点是都对DataBinding做了扩展,看来DataBinding大家都很认可
- 有6个项目都用到了Kotlin,最高达到了96%,看来我们android小伙伴都爱学习,kotlin的普及率好高
- 还有一个点都对MultiItemType做了良好的扩展,说明这确实是一个Adapter库的标配
- 有三个项目对Paging库做了扩展,相信大家用它的机会越来越多
- 头尾布局几乎成了框架的标配
- Kotlin DSL或多或少的支持,写法上简洁而优美
- 大多数都做了比较好的分库处理,按需依赖,不拖泥带水
我们如何做一个可以称之为全而好的Adapter框架呢?
我抽取几个关键词来告诉你
- 适当分包,按需依赖,提供良好的扩展性
- kotlin支持 利用最近一个老铁的话:工欲善其事必先利其器,kotlin绝壁是一个好利器
- DSL扩展 简洁的写法,利于阅读
- DataBinding支持 不用质疑,有就对了
- Paging扩展 在我看来Paging用了很多新的设计,值得我们去学习
- 头尾布局、空布局、上拉加载,拖动,动画 提供专门的包来扩展
- DiffUtil扩展 好的工具不要忘记使用,总会有合适的应用场景
- anko扩展 用了kotlin怎么能不用一下anko layout,300%的布局加载效率提高不香吗?
设计这么一个框架我的坚持是什么?
你有没有陷入过一个误区?自己封装了一个东西,特别的全,什么都支持,一股脑的往里面塞东西,这个人说我想这样,你就改成这样,那个人想那样,你又开始改?难道我们做个东西就是为了让别人指挥吗?答案肯定是:不。那应该从哪几个方面考虑呢?
- 扩展性 对的,你一定要做到可扩展,要不然你就要面临东改改,西改改的困境,如何做到可扩展呢?一条原则搞定:依赖倒转原则,尽量依赖于抽象,而不是依赖于实现,做到这一点其实还不够
- 可靠性 可以理解为,你做的东西不要经常变,特别是抽象的接口,在一开始我们就要做到完整,有的人说,我怎么肯能考虑那么完美呢?那就要考虑一下,你是不是走到了一个误区,接口的抽象在这样一个成熟的框架中,应该很好确定的,接口不要大而全,接口也要做到尽量的小,起码接口可以多继承啊,对吧。
- 里氏替换原则: 任何基类可以出现的地方,子类一定可以出现,这个原则其实好多人都不太理解,其实说白一点,用现实的例子告诉你,你继承了父亲的很多基因,那你能改变父亲的基因吗?肯定不能,可代码里是可以重写的(抽象方法不算哦),但这个原则就是告诉我们避免重写,一旦重写,父类就没有了意义,其实在工作中,有很多人喜欢往父类里抽象很多东西,还特别喜欢在不同的子类中覆盖后重写,这些都是不好的习惯,你不应该只是老三用到了一个东西,就要给所有的人加上这个东西,我感觉是个累赘,你觉得呢?我们在设计框架的时候,一定要遵循这些好的设计原则。
- 单一职责 一个类应该有且仅有一个职责,你还好意思封装一个类,啥功能都有吗?除非它叫Manager,但也只能管理一类东西,职责的单一处处可见,且要处处坚持。
讲了这些废话,你是不是不耐烦了,下面来点干货吧,看看Adapter的一些细节是如何封装的
Adapter 如何做到ItemViewType自动适配?我们是如何封装的?
看源码前,我想说的是,你要明白一个原理,其实ItemViewType它影响的就是ViewHolder的复用逻辑,只要是一样的ItemViewType,它就会触发复用,所以说ItemViewType封装的目的,其实是缓存ViewHolder然后复用,那我们如何做到自动处理加缓存呢?
由于我们要做到onCreateViewHolder的下移,而我们抽象了ViewModel层来负责组织View和Model,那么ViewHolder就成了我们View的载体,抽象一个ViewHolderFactory让ViewModel继承,达到onCreateViewHolder的调用下移
typealias GenericViewHolderFactory = ViewHolderFactory<out RecyclerView.ViewHolder>
interface ViewHolderFactory<VH : RecyclerView.ViewHolder> {
fun getViewHolder(parent: ViewGroup, layoutInflater: LayoutInflater): VH