Adapter的封装之路

原文:Adapter的封装之路

一、几种常见列表效果:



假如要用RecyclerView实现下面的几种效果,你会如何实现呢?

效果1:单布局效果

效果2:多布局效果

有多种Item布局

效果3:多布局多列效果

有多种Item布局,有的Item占1行,有的Item占1/2行

二、使用方法



1.原始的Adapter-单布局效果

在最原始的用法中,我们需要自己去继承RecyclerView.Adapter,然后写一大坨形式化的代码:

然后在Activity中调用这个Adapter,感觉很麻烦有木有?

实现效果如图1。

2.封装后的单布局的Adapter

看!再也不用自己去继承RecyclerView.Adapter,写那么一大坨了,轻轻松松几行代码搞定

实现效果如图1。

3.升级后的多布局的Adapter

使用多布局的Adapter时候呢,我需要实现两个方法了,一个绑定布局,一个用来绑定数据,不过也不算麻烦,比起那些写个多布局写的欲仙欲死的原始写法而言,我们已经很幸福了,不算么?

实现效果如图2。

4.再次升级,多布局-多实体的Adapter

简单的多布局呢,就像聊天界面的发送和接受一样,只是布局不一样,但是布局所使用的数据源其实是一致的,就像3里面一样,都是SimpleBean

但是,还有很多坑爹的多布局呢,不只是布局不一样,连数据源也不一样,如果要:
R.layout.item_super对应SuperBean,
R.layout.item_simple对应SimpleBean,

你会怎么搞?

下面看我的用法!用LayoutWrapper<T>包起来,不就统一成一种实体了么?

为了让不同的布局绑定数据之间尽量解耦,我加了一个新的DataHolder,来专门处理布局--数据的映射关系。

实现效果如图2。

6.究极进化!多布局-多实体-多列的Adapter

我们已经实现了多布局中,每个布局都可以对应一个实体了,但是,这就够了么?no! too native!

要知道,产品的想法、UI的创意,是我们这些凡人永远无法预料的?

你能猜到下一版又会改成什么风格么?额,扯远了,先把上面的效果3实现了再说吧,毕竟,这种效果也是非常非常常见的,也是让很多人觉得头疼的,尤其是,当我们要实现这种效果:

注意哦!里面的车型、车龄、里程等分组项是后台配的,至于每个分组里面的选择项,就更是不用说了。

当一切都是动态可配置的时候,你该何去何从?还敢用线性布局嵌套多个列表来硬编码么?

其实我们发现这个黑不溜秋的界面,其实也就是上面的效果3的升级版,所以,我们只要能实现效果3就可以了。

下面亮大招!

其实RecyclerView的LayoutManager是可以控制每个Item所占的列数的,所以,我们可以在包装类LayoutWrapper里面,再加一个表示列数的字段即可!

使用时,主要注意两点:

  1. GridLayoutManager的列数,应该是所有Item的列数的最小公倍数!比如我有两种Item,分别为一行显示1个和2个,于是最小公倍数是2
  2. LayoutWrapper的表示列数的字段,则是最小公倍数/N,N表示一行显示多少个,比如一行显示1个,则为2,一行显示2个,则为1

实现效果如图3。搞定收工!

其实,你的所有界面,除去导航栏和底部工具栏,中间全部可以用RecyclerView来实现!
每个item表示一块区域,这样分区域的来实现,也是一种很好的解耦思路,避免改了下面的视图,上面的视图莫名其妙的被改了。

三.具体的封装过程:


我想分享的,不仅仅只是工具类,更是封装的思想!

当然,也许我的封装有不妥之处,欢迎和我探讨!@QQ:630709658

1、SingleAdapter:将Adapter从具体到泛型

思路:

  1. 构造时传入layoutId
  2. 数据类型泛化
  3. 提取出万能的SuperViewHolder
  4. bindData的方法抽象化,延迟实现(交由具体的子类实现)

这里还用到了一个封装的万能ViewHolder

2-MultiAdapter:从单布局到多布局

思路:

  1. 构造时传入layoutId数组
  2. 添加layoutMap,记录layoutId--viewType的对应关系
  3. bindLayout的方法抽象化,由子类实现Item--layoutId的对应关系

这里主要有以下两部分:用map存放viewType和layoutId的对应关系

用map.entrySet来根据value读取key

3-SuperAdapter:多布局中,从单实体到多实体

思路:

  1. 将泛型T升级为包装类LayoutWrapper,持有布局id,泛型数据Item,控制器holder
  2. 提取出接口DataHolder,用于实现ViewHolder和ItemData的绑定

这里主要是:
1、定义了布局包装类

2、定义了控制器接口

3、由控制器接口的bind来负责绑定

4-LayoutWrapper:多布局中,配置某项可占据多列

思路:

  1. LayoutWrapper添加spanSize属性,记录该item的列数
  2. 使用时调用gridLayoutManager.setSpanSizeLookup来动态设置列数

然后使用时:

  1. 如果你的代码中,存在着大段相同或极其相似的代码,那么,开始重构吧!
  2. 在不断的重构中,你会发现:实现很重要,如何组织这些实现也同样重要!
  3. 重构两个着力点:数据泛型化、方法抽象化

最后和大家分享一句话:

封装技术的快速提升,来自于对代码的不断重构

当然,没有单元测试作为保障的重构,谁也不敢说自己就不会在重构中:自己把自己给作死了!so,要重构,更要单测!不说了,我继续研究单元测试了,不得不说,Android这个坑货,单元测试还真麻烦,凡是用到了Android系统的API的地方,一律不能用JUnit测试(在不引入Roboletric的情况下)因为:

IDE和SDK只为Android开发者提供了开发和编译一个项目的环境,并没有提供运行这个项目的环境!
开发时使用的android.jar里面的class实现是不完整的,它们只是一些stub,如果你打开android.jar下面的代码去看看,你会发现所有的方法都只有一行实现:throw RuntimeException("stub!!”);
而运行unit test,说白了还是个运行的过程,所以如果你的unit test代码里面有android相关的代码的话,那运行的时候将会抛出RuntimeException("stub!!”)。

额,不小心扯远了。先别说了,把工具类奉上:

所有代码均已上传到:Github,欢迎Star!

文/天然鱼(简书作者)
原文链接:http://www.jianshu.com/p/f530318be47a#
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

时间: 2024-11-10 01:07:32

Adapter的封装之路的相关文章

Android之Adapter的封装与抽象

在开发的过程中,常常会用到ViewPager.ListView.GridView等.这些带有Item的视图控件,而这些控件有个共同点就是都要用到它们的适配器,我们在实现视图展示时,一般都会去写个自定义的适配器去继承PagerAdapter或Adapter或Adapter的子类,因为Android源码自带的这些适配器都比较抽象,往往在我们开发时,写的一些自定义适配器都需要重写Adapter父类的一些方法,在重写时,有很多较通用性的代码,比较耦合,下面将PagerAdapter和Adapter的子类

Adapter分组封装

YCGroupAdapter 01.前沿说明 1.1 案例展示效果 1.2 该库功能和优势 1.3 相关类介绍说明 02.如何使用 2.1 如何引入 2.2 最简单使用 2.3 使用建议 03.常用api 3.1 自定义adapter 3.2 notify相关 3.3 点击事件listener 04.实现步骤 4.1 业务需求分析 4.2 adapter实现多type 4.3 这样写的弊端 4.4 分组实体bean 4.5 构建封装adapter 05.优化相关 06.关于参考 07.其他说明介

window10封装之路

应公司业务需要,封装win10来玩玩.一.使用EasySysprep_4.5进行系统封装的第一阶段1.在workstation安装原版win10;并安装所有需要的软件如输入法.QQ.微信等2.把封装工具(IT天空下载的win10万能驱动-EasyDrv7_win10.x64.iso和封装软件EasySysprep)提前拷贝到虚拟机D盘:3.拷贝所有工具到虚拟机后,为保证兼容性卸掉虚拟机网卡:4.打开Easysysprep开始封装,如下图 二.使用EasySysprep_4.5进行系统封装的第二阶

RecyclerView让列表嵌套如此简单

平常开发时,相信像这样的页面,大家一定是遇到过的.这里比较坑爹的地方在于呢:列表嵌套.订单列表中的每一项,都包含一个商品列表.像这种需求,大家会如何实现呢? 这里呢,说一下我自己的思路,我没有使用列表嵌套,而是,将原有的Order拆分成了三个布局类型:Head.Body.Foot,一个Body就是一个商品,有多个商品就有多个Body. 然后,使用我自己封装的一套Adapter,让多布局更加简单易用.关于我的这个Adapter库,详见:Adapter的封装之路 不过,这里稍稍麻烦的一点就是,得到网

Rxjava+ReTrofit+okHttp深入浅出-终极封装

Rxjava+ReTrofit+okHttp深入浅出-终极封装 背景: 学习Rxjava和retrofit已经很长时间了,功能确实很强大,但是使用起来还是有点复杂,代码的重复性太高,所以决定把基于retrofit和rxjava的处理统一封装起来,实现的功能: 1.Retrofit+Rxjava+okhttp基本使用方法 2.统一处理请求数据格式 3.统一的ProgressDialog和回调Subscriber处理 4.取消http请求 5.预处理http请求 5.返回数据的统一判断 效果: 封装

从头开始学 RecyclerView(三) 封装简化

前言 上一篇的代码,也是基于这些封装的. RV的封装,跟以前的listView之类的封装,大同小异. 这里,从@devwiki 处,将代码搬过来,基本无修改 BaseHolder的优化 使ViewHolder只用来缓存View. 添加SparseArray,使之来缓存View. 添加BaseHolder(View view)构造器,外部更方便控制View. 保留getContext()方法,方便获取Context对象. getView(resid),简化itemView.findviewById

【Android】快速开发偷懒必备,一句话搞定所有ViewGroup的Adapter . 支持自定义ViewGroup

转载请标明出处: http://blog.csdn.net/zxt0601/article/details/53576092 本文出自:[张旭童的博客](http://blog.csdn.net/zxt0601) 代码传送门:喜欢的话,随手点个star.多谢 https://github.com/mcxtzhang/all-base-adapter 概述 开发中,经常会用到动态在ScrollView.LinearLayout里addView的事,尤其是ItemView一样时,每次都要写一大堆代码

自己封装的工具类,使用原生SwipeRefreshLayout+RecycleView实现下拉刷新和加载更多

实现SwipeRefreshLayout+RecycleView实现刷新 在你的xml文件里写上如下代码: <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/SwipeRefreshLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <andr

优雅地实现Android主流图片加载框架封装,可无侵入切换框架

项目开发中,往往会随着需求的改变而切换到其它图片加载框架上去.如果最初代码设计的耦合度太高,那么恭喜你,成功入坑了.至今无法忘却整个项目一行行去复制粘贴被支配的恐惧.:) 那么是否存在一种方式 能够一劳永逸地解决这个痛点呢?下面我们来分析一下图片加载框架面对的现状和解决思路. 问题现状 一个优秀的框架一般在代码设计的时候已经封装很不错了,对于开发者而言框架的使用也是很方便,但是为什么说我们往往还要去做这方面的框架封装呢?原因很简单,实际项目开发中,我们不得不面对着日新月异的需求变化,想要在这个变