Adapter
单布局
ListView/GridView + Adapter可以说是Android程序员最常用的组件了. 我们应该尽量简化Adapter的代码以提高开发效率. 首先来看看不做任何封装的Adapter需要哪些步骤:
继承自BaseAdpter
维护一个List数据并实现4个抽象方法
声明一个ViewHolder
在getView中判断convertView是否为空, 为空则inflate一个布局, 初始化ViewHolder, 初始化控件, 并将ViewHolder通过setTag设置到convertView中.
如果不为空则通过getTag将ViewHolder取出来
为控件设置值
可以看到需要做的事情还是很多的. utils包中有一个ViewHolder类, 此类可以代替自己声明的ViewHolder, 并且不用写将ViewHolder与convertView绑定的代码. 控件可以直接通过如下方式声明:
TextView textView = ViewHolder.get(convertView, R.id.textView);ViewHolder中使用了SparseArray来缓存视图, 内部也是用过给convertView设置tag来达到缓存的目的. 并且通过泛型来避免类型转换. 整体逻辑很简单:
public class ViewHolder {
@SuppressWarnings("unchecked")
public static <T extends View> T get(View view, int id) {
SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
if (viewHolder == null) {
viewHolder = new SparseArray<>();
view.setTag(viewHolder);
}
View childView = viewHolder.get(id);
if (childView == null) {
childView = view.findViewById(id);
viewHolder.put(id, childView);
}
return (T) childView;
}
}下面的内容详细可以参考 打造万能的ListView GridView 适配器
虽然有了ViewHolder能减少很多代码量, 但是这不是极限, 还可以继续减少. 比如内部维护的List数据, 另外三个抽象方法等都是可以不用写的. 这里我们引用GitHub上的一个开源工具 base adapter helper. 现在来看看如何使用base adapter helper:
可以调用如下方法修改Adapter的数据
base adapter helper的原理在此处就不赘述了, 参考 Android base-adapter-helper 源码分析与扩展. 使用base adapter helper可以减少大量重复的代码, 也可以通过扩展BaseAdapterHelper以适应自己的编程习惯.
接下来看看base adapter helper的getItemId方法的实现:
很多时候, getItemId的返回值都是position. 如果我们需要拿到实体类的id, 就必须这么写:
通常情况下, ListView中的某些控件是需要与网络API交互的, 而基本上网络API需要的只是一条数据的id. 因此我改造了getItemId方法, 在某些情况下, 此方法能直接返回实体类中的id.
上述的某些情况就是指T类型实现了IdObject接口. 以上就是对Android适配器的简化及优化. 但是base adapter helper使用虽然简单, 也还是有不足的地方. 比如不支持多布局, 只支持BaseAdapter, 不支持其他类型比如ViewPager的Adapter等.
以上就是单布局的基本原理与使用方法. 单布局是APP中最常用的, 下面介绍不是很常见的多布局的封装.
多布局
多布局是指一个适配器中使用一个以上的布局文件. 主要是依赖于覆写BaseAdapter中的getViewTypeCount与getItemViewType方法. 多布局使用了代理, 将convert方法代理给多个代理类去实现, 有兴趣的可以看这里, 这里只讲使用方法. 直接上代码:
效果:

两个布局的差别就是一个TextView的gravity是left, 同时有margin值, 另一个的gravity为right, 没有margin值. 如果是双数则显示gravity是left的TextView, 否则显示gravity是right的TextView. 代码也比较好理解, 接下来看看Delegate接口的声明以及每个方法的含义:
ItemViewDelegate继承了BaseItemViewDelegate, 同时声明H为BaseAdapterHelper, 所以在不需要自定义AdapterHelper的情况下, 建议直接使用ItemViewDelegate:
RecyclerView
作为目前超级灵活超级NB的杀手级控件 - RecyclerView, 怎么能少了它呢? 直接上代码:
使用方法与ListView/GridView一样, 只不过继承从QuickAdapter变成RecyclerAdapter. 多布局也一样, 区别只是从QuickMultiAdapter换成RecyclerMultiAdapter. 下面看一个多布局的例子:
首先是效果:

示例中有两种布局, 一种是日期, 一种是课程详情. 日期占满一行, 详情占半行. XML以及实体省略:
除了Adapter的代码外, 其他均是RecyclerView的基本用法, 如使用SpanSizeLookup来设置每个条目占用的单元数, 使用ItemDecoration来控制条目之间的间隔等.
Last updated
Was this helpful?