今天来复习下android中基本上天天都在用的一种设计模式,适配器模式,对于android的每一个ListView或者RecycleView,我们都需要用一个adapter来适配它每一个Item的布局。像这种将原本两个不兼容的接口通过一个适配器来使得他们能够相互沟通作用的模式就是适配器模式。
如何还没有理解适配器模式的定义的话,那么通过接下来的例子相信大家就知道什么是适配器了。比如现在有一台电脑、和一张sd卡,我们需要将sd卡里的东西保存到电脑里,首先你想到的是什么?是读卡器,只有有了读卡器。我们才能够将sd卡和电脑的usb接口所关联。那么这里的读卡器就是适配器了,它的作用就是sd卡对外提供的读写接口和电脑的usb接口之间的桥梁。
适配器模式的优点:
适配器模式的分类:
类适配器模式 -- 这种类型一般用在一个新的类需要旧的类中个某些方法,但又不完全相同,这时可以将需要的不同的方法提取成一个接口,新的类通过继承旧的类并实现这个接口的方式来适配新的需求。
对象适配器模式 -- 这种方式是将所需的旧的类当做一个参数传入到构造函数中来构造新类,并且实现其他接口来扩展新的需求。
接口适配器模式 -- 这种方式是在旧的类的基础上创建一个抽象类并且去实现新的需求接口,有多少不同的就可以实现多少个接口,然后新的类直接继承这个抽象类就可以满足所有的适配需求了,这种方式就是现如今常用的适配器模式。
Adapter模式安卓中最常用的地方相信都知道,就是ListView的使用上,下面就以一个ListView使用的例子来说明下。首先我们需要在布局中添加ListView控件。
接着在对应的Activity或者Fragment中初始化ListView,并对其添加适配器。
private void initListView() {
listView = findViewById(R.id.list_view);
String[] ctype = new String[]{"新增支出", "新增收入", "我的支出", "我的收入", "数据管理", "系统设置"};
ArrayAdapter arrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_single_choice, ctype);
listView.setAdapter(arrayAdapter);
}
好了,至此ListView的使用已经完成了。但这些不是重点,重点是这里我们对ListView添加的适配器ArrayAdapter。
public class ArrayAdapter extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
public ArrayAdapter(@RecentlyNonNull Context context, int resource) {
throw new RuntimeException("Stub!");
}
... ...
public void add(@RecentlyNullable T object) {
throw new RuntimeException("Stub!");
}
public void addAll(@RecentlyNonNull Collection extends T> collection) {
throw new RuntimeException("Stub!");
}
public void addAll(T... items) {
throw new RuntimeException("Stub!");
}
public void insert(@RecentlyNullable T object, int index) {
throw new RuntimeException("Stub!");
}
public void remove(@RecentlyNullable T object) {
throw new RuntimeException("Stub!");
}
public void clear() {
throw new RuntimeException("Stub!");
}
public void sort(@RecentlyNonNull Comparator super T> comparator) {
throw new RuntimeException("Stub!");
}
@RecentlyNonNull
public Context getContext() {
throw new RuntimeException("Stub!");
}
... ...
@RecentlyNonNull
public static ArrayAdapter createFromResource(@RecentlyNonNull Context context, int textArrayResId, int textViewResId) {
throw new RuntimeException("Stub!");
}
}
public class SimpleAdapter extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
public SimpleAdapter(Context context, List extends Map> data, int resource, String[] from, int[] to) {
throw new RuntimeException("Stub!");
}
... ...
public SimpleAdapter.ViewBinder getViewBinder() {
throw new RuntimeException("Stub!");
}
public void setViewBinder(SimpleAdapter.ViewBinder viewBinder) {
throw new RuntimeException("Stub!");
}
... ...
public interface ViewBinder {
boolean setViewValue(View var1, Object var2, String var3);
}
}
可以看到ArrayAdapter是继承了抽象类BaseAdapter的,并实现了Filterable和ThemedSpinnerAdapter这两个接口来扩展自身的需求。我们再来看看SimpleAdapter类,同样也是继承抽象类BaseAdapter,并实现了Filterable和ThemedSpinnerAdapter。而这里的接口ThemedSpinnerAdapter又是继承自SpinnerAdapter。
public interface ThemedSpinnerAdapter extends SpinnerAdapter {
void setDropDownViewTheme(@RecentlyNullable Theme var1);
@RecentlyNullable
Theme getDropDownViewTheme();
}
一般情况下我们为了实现复杂了ListView自定义的adapter也同样要继承自BaseAdapter,而BaseAdapter也是实现了ListAdapter和SpinnerAdapter两个接口。
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
public BaseAdapter() {
throw new RuntimeException("Stub!");
}
... ...
}
public interface SpinnerAdapter extends Adapter {
View getDropDownView(int var1, View var2, ViewGroup var3);
}
SprinnerAdapter接口又是继承自Adapter。由于JAVA里不能多继承,这里则是通过接口继承的方式来间接的实现多继承,至此,无论是android给我们提供的扩展SimpleAdapter、ArrayAdapter,又或者是需要我们自定义的Adapter都最终实现了Adapter接口.。
public interface Adapter {
int IGNORE_ITEM_VIEW_TYPE = -1;
int NO_SELECTION = -2147483648;
void registerDataSetObserver(DataSetObserver var1);
void unregisterDataSetObserver(DataSetObserver var1);
int getCount();
Object getItem(int var1);
long getItemId(int var1);
boolean hasStableIds();
View getView(int var1, View var2, ViewGroup var3);
int getItemViewType(int var1);
int getViewTypeCount();
boolean isEmpty();
@RecentlyNullable
default CharSequence[] getAutofillOptions() {
throw new RuntimeException("Stub!");
}
}
看到Adapter里的方法是不是很熟悉呢,getCount()计算数据长度、getItem()根据下标获取某一个item等等,这些个方法都是自定义Adapter时需要我们去具体实现的。至此,ListView中Adapter的运用已经梳理完毕了,这里的适配器模式就是前面所提到的接口适配器模式,而BaseAdapter就是被抽象出来的基本类。