1. 程式人生 > >淺談安卓BaseAdapter

淺談安卓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 資料繫結用到了觀察者模式,觀察者模式可參考我的另一篇部落格:

歡迎大家留言評論,共同學習進步.