Class Overview
Common base class of common
implementation for an
BaseAdapter是一个抽象类,是所有适配器的基类,基于BaseAdapter实现的适配器既可以用于ListView(通过实现ListAdapter接口)也可以用于Spinner(通过实现SpinnerAdapter接口).
类BaseAdapter对ListAdapter接口和SpinnerAdapter接口中的某些方法做了默认实现,其实现细节如下:
public abstract
class BaseAdapter implements ListAdapter, SpinnerAdapter {
//提供一些方法,当数据改变时调用注册的DataSetObserver的回调函数
private
final DataSetObservable mDataSetObservable = new
DataSetObservable();
public
boolean hasStableIds() {
return false;
}
public void
registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void
unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
//通知相关联的视图,相应的数据已经改变
public void
notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
public void
notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
public
boolean areAllItemsEnabled() {
return true;
}
public
boolean isEnabled(int position) {
return true;
}
//默认情况getDropDownView()是通过getView()来产生下拉项视图的.
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
return getView(position, convertView, parent);
}
public int getItemViewType(int position) {
return 0;
}
public int
getViewTypeCount() {
return 1;
}
public
boolean isEmpty() {
return getCount() == 0;
}
}
由上可知,BaseAdapter将getView(),getItem(),getCount(),getItemId()四个方法留给了开发者来实现.接下来开始讨论具体的Adapter
ArrayAdapter
类概述
类ArrayAdapter是一个具体的BaseAdapter,其对应的底层数据可以是任意类型的数组或List类型的集合,默认情况下该类期望提供的一个布局文件,该布局文件仅仅只包含一个TextView.你也可以指定一个Layout并指定该布局文件中一个类型为TextView的资源的ID.
默认情况下,ArrayAdapter为每一个数据项生成一个TextView视图对象,并将数据项toString()方法返回的值作为TextView内容.如果想使用其它的视图对象来显示数据项,比如ImageView又或则想显示除数据项toString()方法返回值以外的数据,可以通过覆写getView()方法.
构造器:
public ArrayAdapter(Context context, int textViewResourceId)
{
init(context, textViewResourceId, 0, new
ArrayList());
}
public ArrayAdapter(Context context, int resource, int
textViewResourceId) {
init(context, resource, textViewResourceId, new
ArrayList());
}
public ArrayAdapter(Context context, int textViewResourceId, T[]
objects) {
init(context, textViewResourceId, 0, Arrays.asList(objects));
}
public ArrayAdapter(Context context, int resource, int
textViewResourceId, T[] objects) {
init(context, resource, textViewResourceId,
Arrays.asList(objects));
}
public ArrayAdapter(Context context, int textViewResourceId,
List objects) {
init(context, textViewResourceId, 0, objects);
}
public ArrayAdapter(Context context, int resource, int
textViewResourceId, List objects)
{
init(context, resource, textViewResourceId, objects);
}
最多有4个参数,分别为当前Context,layout(可省),TextView的资源ID与数据(可为数组或List),在构造函数中都调用了一个叫init的函数
private void init(Context context, int resource, int
textViewResourceId, List objects)
{
mContext = context;
mInflater =
(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mResource = mDropDownResource = resource;
mObjects = objects;
mFieldId = textViewResourceId;
}
分别赋值给类中的私有域,mInflater为LayoutInflater,产生相应项的视图。
类中有两个域保存数据
private ArrayList
mOriginalValues;
private List mObjects;
其中mOriginalValues用于过滤数据时保存过滤前的数据,将过滤后的数据存入mObjects。
在ArrayAdapter中还定义了add,insert,remove,clear函数用于改变数据,并定义了一个布尔变量mNotifyChange用于表示用这些函数改变数据后是否通知视图(调用notifyDataSetChanged,调用这个函数时会把mNotifyChange置为true。
一些函数的实现:
public int getCount() {
return
mObjects.size();
}
public T getItem(int position) {
return
mObjects.get(position);
}
public int getPosition(T item) {
return
mObjects.indexOf(item);
}
public long getItemId(int position) {
return
position;
}
public View getView(int position, View convertView, ViewGroup
parent) {
return
createViewFromResource(position, convertView, parent,
mResource);
}
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
return
createViewFromResource(position, convertView, parent,
mDropDownResource);
}
可以看到getView和getDropDownView都通过调用createViewFromResourse来产生视图。
private View createViewFromResource(int position, View convertView,
ViewGroup parent,
int resource) {
View view;
TextView text;
if (convertView == null) {
view = mInflater.inflate(resource, parent, false);
} else {
view = convertView;
}
try {
if (mFieldId == 0) {
// If no custom field is assigned, assume the
whole resource is a TextView
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the
layout
text = (TextView) view.findViewById(mFieldId);
}
} catch (ClassCastException e) {