本文目录
几个重要类的源码
以下是Android 6.0版本的源代码。
/frameworks/base/core/java/android/widget/Adapter.java
Adapter.java
public interface Adapter {
...
int getCount();
Object getItem(int position);
View getView(int position, View convertView, ViewGroup parent);
boolean isEmpty();
...
}
ListAdapter.java
/frameworks/base/core/java/android/widget/ListAdapter.java
public interface ListAdapter extends Adapter {
public boolean areAllItemsEnabled();
boolean isEnabled(int position);
}
BaseAdapter.java
/frameworks/base/core/java/android/widget/BaseAdapter.java
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
...
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
...
public boolean isEnabled(int position) {
return true;
}
...
public int getViewTypeCount() {
return 1;
}
public boolean isEmpty() {
return getCount() == 0;
}
}
ArrayAdpater.java
/frameworks/base/core/java/android/widget/ArrayAdapter.java
public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
private List<T> mObjects;
...
public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull List<T> objects) {
this(context, resource, 0, objects);
}
public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
@NonNull List<T> objects) {
mContext = context;
mInflater = LayoutInflater.from(context);
mResource = mDropDownResource = resource;
mObjects = objects;
mFieldId = textViewResourceId;
}
public int getCount() {
return mObjects.size();
}
public T getItem(int position) {
return mObjects.get(position);
}
public View getView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(mInflater, position, convertView, parent, mResource);
}
private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
ViewGroup parent, int resource) {
View view;
TextView text;
if (convertView == null) {
view = inflater.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) {
Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
throw new IllegalStateException(
"ArrayAdapter requires the resource ID to be a TextView", e);
}
T item = getItem(position);
if (item instanceof CharSequence) {
text.setText((CharSequence)item);
} else {
text.setText(item.toString());
}
return view;
}
}
ArrayAdapter的具体使用
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class Demo13Activity extends Activity {
private ListView lv;
private ArrayList<String> list = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv = (ListView)findViewById(R.id.listview);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this,
android.R.layout.simple_expandable_list_item_1,
getData());
lv.setAdapter(adapter);
}
private ArrayList<String> getData()
{
list.add("180平米的房子");
list.add("一个勤劳漂亮的老婆");
list.add("一辆宝马");
list.add("一个强壮且永不生病的身体");
list.add("一个喜欢的事业");
return list;
}
}
ListView.java
/frameworks/base/core/java/android/widget/ListView.java
public class ListView extends AbsListView {
......
@Override
public void setAdapter(ListAdapter adapter) { //这里需要的是ListAdapter接口类型的入参
...
}
......
}
对象适配器模式
类适配器模式的三个角色:
- 目标接口(dst: destination 目标,目的)
- 源类(src:source 源)
- 适配器
ListView做为client,它需要的目标接口(target interface)就是ListAdapter接口。
源类是数据源:ArrayList<String>
适配器是ArrayAdapter
ArrayAdapter在构造器中接受了ArrayList对象,赋值给private List<T> mObjects;
。又通过mObject
成员变量实现getCount(),getItem(),getView()方法。
所以ListView中的适配器模式是对象适配器模式,并不是类适配器模式。
ArrayAdapter解决了什么问题或者作用是什么?
完成了ArrayList<String>
到ListAdapter的转换。
使用的时候给的源数据是ArrayList<String>
, ListView需要的是ListAdapter,ArrayAdapter完成了从ArrayList<String>
到ListAdapter的转换。
结论:ListView中的适配器模式是对象适配器模式,并不是类适配器模式。
这篇文章:Android设计模式系列-适配器模式 分析的蛮好,但是有误导。