基础
适配器模式
将一个类的接口转换成客户希望的另外一个接口, Adapter
模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
Android
中适配器模式的运用
Android
中的 ListView
、 GridView
、 Spinner
、 AutoCompleted
等 AdapterView
在做视图展示时需要填充数据,但是每个视图的显示效果,需要的数据等等都不一样,所以增加了一个 Adapter
层来应对变化。
常用的 Adapter
BaseAdapter
抽象类,自定义Adapter
实现该类,拥有较高的灵活性ArrayAdapter
支持泛型操作,最为简单,常用来展示一行文本SimpleCursorAdapter
绑定查询到的Cursor
游标到视图上,字段和View
的id
对应起来SimpleAdapter
有最好的扩充性,可以自定义出各种效果,需要实现数据填充
Adapter
对应的常用系统自带布局文件
1 | // 单行文本TextView |
ArrayAdapter
介绍
源码分析
用来显示至少包含一行 TextView
的字符串列表
1 | // 定义,泛型操作,T 可以是简单数据类型,也可以是自定义的类(需要实现 toString ) |
示例
根据源码构造函数的分析,我们常用的有如下三种:
- 简单字符串显示
- 自定义布局
- 自定义数据集合
1 | // 展示三种 ArrayAdapter 的用法 |
如上代码对应的效果图:
SimpleCursorAdapter
介绍
类定义
1 | // 类定义 |
注意:
CursorAdapter
中的Cursor
必须包含一列 “_id”,也就是查询时projection
中要包含_id
,但UI
中并不需要显示这列
具体示例及错误分析
1 | // 例子使用 CursorLoader 异步加载 |
swapCursor
的源码分析
CursorAdapter.java
文件中:
SimpleAdapter
介绍
SimpleAdapter
的扩展性最好,可以定义各种各样的布局出来,可以显示比较复杂的列表,包括每行显示图片、文字等,只是简单的负责显示。
使用 SimpleAdapter
的数据用一般都是 HashMap
构成的 List
。HashMap
的每个键值数据映射到布局文件中对应 id
的组件上。因为系统没有对应的布局文件可用,我们可以自己定义一个布局。
构造函数
1 | public SimpleAdapter(Context context, List<? extends Map<String, ?>> data, |
参数说明:
- context
- data
由Map(String ,Object)
列表填充的数据集合 - resource
界面布局文件 - from
数据Map
集合中的key
- to
布局文件中各组件id
,和Map
集合中的key
需要一一对应,资源数据按照这个对应关系来填充值
系统默认支持的布局
默认布局中支持如下控件:
- Checkable
- TextView
- ImageView
参考 bindview
源码:
1 | // SimpleAdapter.java:: bindview,代码部分有删减 |
参考源码,按以下顺序绑定数据:
- Checkable
如果View
实现了Checkable
(例如CheckBox
),期望绑定值是一个布尔类型 - TextView
期望绑定值是一个字符串类型,通过调用setViewText(TextView, String)
绑定数据 - ImageView
期望绑定值是一个资源id
或者一个字符串,通过调用setViewImage(ImageView, int)
或setViewImage(ImageView, String)
绑定数据
如果没有一个合适的绑定发生将会抛出 IllegalStateException
自定义布局
自定义布局中如果包含了不是系统默认支持控件,需要实现 ViewBinder
接口
1 | public static interface ViewBinder { |
BaseAdapter
介绍
类定义及重写
类定义:public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {...}
重写四个方法:
1 | public int getCount() {...} |
其中 getView
最关键,特别是数据很多时如果全部加载会非常消耗资源,导致 ListView
滑动慢,常用的解决方案是:convertView + ViewHolder
方案
ViewHolder
的意义
ViewHolder
是一个静态类, 用来缓存了显示数据的视图,加快 UI
的响应速度。
To work efficiently the adapter implemented here uses two techniques:
(译:提升 Adapter 性能的两种方法:)
-It reuses the convertView passed to getView() to avoid inflating View when it is not necessary
(译:重用缓存 convertView 传递给 getView() 方法来避免填充不必要的视图)
-It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary
(译:使用 ViewHolder 模式来避免没有必要的调用 findViewById():因为太多的 findViewById 也会影响性能)
ViewHolder类的作用
-The ViewHolder pattern consists in storing a data structure in the tag of the view
returned by getView().This data structures contains references to the views we want to bind data to, thus avoiding calling to findViewById() every time getView() is invoked
(译:ViewHolder 模式通过 getView() 方法返回的视图的标签 Tag 中存储一个数据结构,这个数据结构包含了指向我们要绑定数据的视图的引用,从而避免每次调用 getView() 的时候调用 findViewById())
示例
1 | // 静态类ViewHolder |
Spinner
介绍
标准用法
定义布局文件和下拉布局,并填充数据
1 | Spinner spinner = (Spinner)findViewById(R.id.spinner_show_checkedtextview); |
Spinner
显示样式和下拉菜单样式的区别:
如果 Adapter
不设置 setDropDownViewResource
,默认下拉菜单和显示使用同一个布局。
两种模式
默认模式为 dropdown
1 | android:spinnerMode="dialog" |