淺談安卓BaseAdapter
一:繼承結構
經常用Adapter,今天抽出點時間看看BaseAdapter的原始碼,抽象類BaseAdapter實現了ListAdapter,SpinnerAdpter介面,ListAdapter和SpinnerAdpter均繼承自Adapter介面,組織結構如下圖所示:
由於BaseAdapter實現ListAdapter ListAdapter,SpinnerAdpter的時候並沒有重寫這四個抽象方法,所以轉給BaseAdapter的子類去實現.
至於ListAdapter 中只有兩個抽象方法:
public boolean areAllItemsEnabled(); boolean isEnabled(int position);
BaseAdapter已經重寫這兩個方法並且返回true,許可權為public,所以我們自己的介面卡可以使用這兩個方法,決定條目是否Enabled.
最後一個SpinnerAdpter spinner是紡紗工的意思,紡紗工介面卡,意思時不斷的像紡紗機一樣重新整理檢視.這個介面卡只有一個抽象方法:
public View getDropDownView(int position, View convertView, ViewGroup parent);
BaseAdapter 中重寫了該方法:
public View getDropDownView(int position, View convertView, ViewGroup parent) { return getView(position, convertView, parent); }
BaseAdapter 中除了四個需要繼承者需要實現的方法外,其餘Adapter抽象方法均已重寫,其中兩個方法,
notifyDataSetChanged() 和notifyDataSetInvalidated() 是BaseAdapter自己獨有的方法.
二:BaseAdpter資料繫結
BaseAdapter 的資料繫結用到了觀察者模式,DataSetObserver,DataSetObservable,Observable
DataSetObserver原始碼:
public abstract class DataSetObserver { /** * 當整個資料集發生更改時呼叫此方法 */ public void onChanged() { // Do nothing } /** * 當整個資料無效時呼叫此方法 */ public void onInvalidated() { // Do nothing }
DataSetObservable原始碼:其中用到了synchronized,因為ArrayList是執行緒不安全的,如果ArrayList換做Vector (執行緒安全,效率低)也是可以的,此時就不需要synchronized了.
public class DataSetObservable extends Observable<DataSetObserver> {
/**
*當資料集的內容發生變化時呼叫。接受者
*將在下次查詢資料集時獲取新內容。
*/
public void notifyChanged() {
synchronized(mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
/**
*當資料集不再有效且不能再次查詢時呼叫
*例如當資料集已關閉時。
*/
public void notifyInvalidated() {
synchronized (mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
Observable原始碼:
public abstract class Observable<T> {
protected final ArrayList<T> mObservers = new ArrayList<T>();
/**
*新增觀察者
*/
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already
registered.");
}
mObservers.add(observer);
}
}
/**
*移除觀察者
*/
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
/**
* 移除所有已註冊的觀察者
*/
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
註釋已經翻譯為中文.
BaseApter在notifyDataSetChanged()方法中呼叫:mDataSetObservable.notifyChanged(),當資料發生變化時呼叫notifyDataSetChanged()方法,重新整理檢視.
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 void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
至此BaseAdapter的組織結構和資料結構已經展示完畢,且看下次分析Adapter如何與ListView 進行繫結,即:setAdapter方法.
BaseAdapter 資料繫結用到了觀察者模式,觀察者模式可參考我的另一篇部落格:
歡迎大家留言評論,共同學習進步.