Adapter相当于一个数据源,可以给AdapterView提供数据,并根据数据创建对应的UI,可以通过调用AdapterView的setAdapter方法使得AdapterView将Adapter作为数据源。
常见的AdapterView的子类有ListView、GridView、Spinner和ExpandableListView等。
本文就以ListView为例讲解各种常见的Adapter的使用。
以下是Adapter相关类的关系图:
Adapter接口
Adapter源码链接如下:
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/Adapter.java
Adapter接口定义了如下方法:
- public abstract void registerDataSetObserver (DataSetObserver observer)
Adapter表示一个数据源,这个数据源是有可能发生变化的,比如增加了数据、删除了数据、修改了数据,当数据发生变化的时候,它要通知相应的AdapterView做出相应的改变。为了实现这个功能,Adapter使用了观察者模式,Adapter本身相当于被观察的对象,AdapterView相当于观察者,通过调用registerDataSetObserver方法,给Adapter注册观察者。 - public abstract void unregisterDataSetObserver (DataSetObserver observer)
通过调用unregisterDataSetObserver方法,反注册观察者。 - public abstract int getCount ()
返回Adapter中数据的数量。 - public abstract Object getItem (int position)
Adapter中的数据类似于数组,里面每一项就是对应一条数据,每条数据都有一个索引位置,即position,根据position可以获取Adapter中对应的数据项。 - public abstract long getItemId (int position)
获取指定position数据项的id,通常情况下会将position作为id。在Adapter中,相对来说,position使用比id使用频率更高。 - public abstract boolean hasStableIds ()
hasStableIds表示当数据源发生了变化的时候,原有数据项的id会不会发生变化,如果返回true表示Id不变,返回false表示可能会变化。Android所提供的Adapter的子类(包括直接子类和间接子类)的hasStableIds方法都返回false。 - public abstract View getView (int position, View convertView, ViewGroup parent)
getView是Adapter中一个很重要的方法,该方法会根据数据项的索引为AdapterView创建对应的UI项。
ListAdapter接口
ListAdapter接口继承自Adapter接口,ListAdapter源码链接如下:
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/ListAdapter.java
ListAdapter可以作为AbsListView的数据源,AbsListView的子类有ListView、GridView和ExpandableListView。
ListAdapter相比Adapter新增了areAllItemsEnabled和isEnabled两个方法。
SpinnerAdapter接口
SpinnerAdapter接口继承自Adapter接口,SpinnerAdapter源码链接如下:
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/SpinnerAdapter.java
SpinnerAdapter可以作为AbsSpinner的数据源,AbsSpinner的子类有Gallery, Spinner和AppCompatSpinner。
相比Adapter,SpinnerAdapter中新增了getDropDownView方法,该方法与Adapter接口中定义的getView方法类似,该方法主要是供AbsSpinner调用,用于生成Spinner下拉弹出区域的UI。在SpinnerAdapter的子类BaseAdapter中,getDropDownView方法默认直接调用了getView方法。
ArrayAdapter和SimpleAdapter都重写了getDropDownView方法,这两个类中的getDropDownView方法与其getView的方法都调用了createViewFromResource方法,所以这两个类中方法getView与方法getDropDownView代码基本一致。
CursorAdapter也重写了getView与getDropDownView方法,虽然这两个方法没有使用公共代码,但是这两个方法代码逻辑一致。
综上,我们可知当我们在覆写getDropDownView方法时,应该尽量使其与getView的代码逻辑一致。
BaseAdapter抽象类
BaseAdapter是抽象类,其实现了ListAdapter接口和SpinnerAdapter接口,其源码链接如下:
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/BaseAdapter.java
BaseAdapter主要实现了以下功能:
– BaseAdapter实现了观察者模式,Adapter接口定义了方法registerDataSetObserver和unregisterDataSetObserver,BaseAdapter中维护了一个DataSetObservable类型的变量mDataSetObservable,并实现了方法registerDataSetObserver和unregisterDataSetObserver。
- BaseAdapter重写了getDropDownView方法,其调用了getView方法,如下所示:
123public View getDropDownView(int position, View convertView, ViewGroup parent) {return getView(position, convertView, parent);} - 覆写其他一些方法,设置了默认值,比如覆写hasStableIds方法,使其默认返回false
ArrayAdapter类
类ArrayAdapter继承并实现了BaseAdapter抽象类,其源码链接如下:
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/ArrayAdapter.java
ArrayAdapter是最简单的Adapter,AdapterView会将ArrayAdapter中的数据项调用toString()方法,作为文本显示出来。
ArrayAdapter的使用代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
package com.ispring.adapter; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = (ListView)findViewById(R.id.listView); String[] values = {"iPhone","小米","三星","华为","中兴","联想","黑莓","魅族"}; //List list = Arrays.asList(values); //Arrays.asList(values)返回的是一个只读的List,不能进行add和remove //new ArrayList(Arrays.asList(values))则是一个可写的List,可以进行add和remove List list = new ArrayList(Arrays.asList(values)); final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list); listView.setAdapter(adapter); //单击item之后,删除对应的item listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView> parent, View view, int position, long id) { String item = adapter.getItem(position); adapter.remove(item); Toast.makeText(MainActivity.this, item, Toast.LENGTH_SHORT).show(); } }); } } |
界面如下所示:
我们绑定了ListView的OnItemClickListener事件,当单击其中一项的时候就会通过ArrayAdapter的remove()方法删除对应项。
ArrayAdapter有以下几个构造函数: