Android之Adapter用法总结
1:概念
Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带。在常见的View(List View,Grid View)等地方都需要用到Adapter。如下图直观的表达了Data、Adapter、View三者的关系:
Android中所有的Adapter一览:
由图可以看到在Android中与Adapter有关的所有接口、类的完整层级图。在我们使用过程中可以根据自己的需求实现接口或者继承类进行一定的扩展。比较常用的有 BaseAdapter,ArrayAdapter,SimpleAdapter,SimpleCursorAdapter等。
· BaseAdapter是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性;
· ArrayAdapter支持泛型操作,最为简单,只能展示一行字。
· SimpleAdapter有最好的扩充性,可以自定义出各种效果。
· SimpleCursorAdapter 可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现更复杂的UI也可以重写其他方法。可以认为是 SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来。
2.应用案例
1)ArrayAdapter
列表的显示需要三个元素:
a.ListVeiw用来展示列表的View。
b.适配器 用来把数据映射到ListView上的中介。
c.数据 具体的将被映射的字符串,图片,或者基本组件。
案例一
这里要说明的是android.R.layout.simple_expandable_list_item_1,是android系统自带的布局文件。
运行的效果图如下:
案例二
这里要说明的是android.R.layout.simple_expandable_list_item_1,是android系统自带的布局文件。
运行的效果图如下:
上面代码使用了Adapter(Context context, int resourcefulness, List<T> objects)来装配数据,要装配这些数据就需要一个连接List View视图对象和数组数据的适配器来两者的适配工作,Adapter的构造需要三个参数,依次为this,布局文件(注意这里的布局文件描述的是列表的每一行的布局,android.R.layout.simple_list_item_1是系统定义好的布局文件只显示一行文字,数据源(一个List集合)。同时用adapter()完成适配的最后工作。
2)SimpleAdapter
simpleAdapter的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上 Button(按钮),CheckBox(复选框)等等。下面的代码都直接继承了ListActivity,ListActivity和普通的 Activity没有太大的差别,不同就是对显示ListView做了许多优化。
案例一
对应的布局文件如下:
对应的activity如下:
运行的效果如下:
说明:
使用SimpleAdapter的数据用一般都是Hash Map构成的List,list的每一个节点对应adapter的每一行。Hash Map的每个键值数据映射到布局文件中对应id的组件上。因为系统没有对应的布局文件可用,我们可以自己定义一个布局simple_adapter1.xml。下面做适配,new一个SimpleAdapter其中的参数依次是:this,布局文件(simple_adapter1.xml),Hash Map的 img 和 title。布局文件中组件对应的id依次为R.id.img和 R.id.title。Hash Map的各元素分别映射到布局文件的各组件上,完成适配。
3)SimpleCursorAdapter
需要说明的是:本来参照下面代码进行验证,发现是错的,请客官跳过此SimpleCursorAdapter; 后续会更新此SimpleCursorAdapter,
4)BaseAdapter
有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器, 然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研究一下 ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter。下面的示例将显示一个按钮和一个图片,两行字如果单击按钮将删除此按钮的所在行。并告诉你ListView究竟是如何工作的。
base_adapter.xml如下:
ListView如下:
ViewHolder如下:
自定下adapter如下:
下面将对上述代码,做详细的解释,listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度,然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。
系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中 inflate来的布局。我们用LayoutInflater的方法将定义好的base_adapter.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那再绘制下一行,直到绘完为止。在实际的运行过程中会发现 listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。
效果图如下:(这里的bug是没有写点击事件,因为没把listiew传过来)
对于上面 4)BaseAdapter 中的代码中,按钮触发事件不会写,是因为不会传listview,下面的代码是整理后的代码。
重新整理后的代码如下:
base_adapter.xml 没有改变
ListView如下:(showInfo()方法放在自定义adapter)
ViewHolder 没有改变
自定下adapter如下:
总结:
遇到的问题是:
Cp3ListView.java中的showInfo()方法
移植到Cp3Adapter.java中去,
注意这里遇到的问题是 context 的问题;Cp3ListView.java中的showInfo()方法中的new AlertDialog.Builder(this)中的this是当前activity; 移植到Cp3Adapter.java中去后,变成了new AlertDialog.Builder(context),注意这里的context用法。
最后:这样修改之后,按钮触发事件就有反应了。