Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android編程入門 >> android中的所謂觀察者模式

android中的所謂觀察者模式

編輯:Android編程入門

    生活中我們常認定某些人很有才,但什麼是有才呢?明朝的王守仁曾這樣解釋:才,是所謂天理,應用到物上,便成了才。凡事凡物,只要掌握了所謂科學的方法,並能靈活運用,那麼你也可以成為一個有才的人。

    觀察者模式是軟件設計都會運用到的一種模式,無論何種預言,由於本人是android猿類,所以本篇僅探討android中的觀察者模式,為了詳致地闡述這一模式,本文分為三個部分:概念、簡單實現、android中listview的具體實現。看完這三部分,相信您自己也能夠駕輕就熟地在自己的軟件中編寫觀察者模式了。

   每逢花晨月夕,便有絲竹管弦之興,美文就要來襲了:)

   一、概念

  •    定義 觀察者模式是由一個發送者(發送者是筆者自己的稱呼,覺較之被觀察者貼切得多)和一個觀察者構成的、發送者在狀態改變時(用戶操作、程序主動改變等)主動通知所有觀察者作相應的刷新。
  •    作用 面向對象的設計原則之一就是特定的對象干特定的事,比如眼睛對象和大腦對象 ,眼睛只需負責看,將看到的信息傳給大腦,大腦只負責根據 接收到的信息作出對應的反應。觀察者模式提供了良好的解耦。
  •    理論實現 觀察者模式定義了對象之間一對多的的依賴關系,以便一個對象的狀態發生改變時,所有依賴於他的對象都能夠得到通知,並自動刷新。ps:這句話是復制的,如果你看得似是而非,請帶著疑問看完簡單實現部分就明白了。
  •    成員介紹 觀察者:(Observer)將自己注冊到被觀察對象(Subject)中,被觀察對象將觀察者存放在一個容器(Container)裡。被觀察者:被觀察對象發生了某種變化,從容器中得到所有注冊過的觀察者,將變化通知觀察者
  • 圖示

    二、簡單實現

     依照圖示,上代碼:首先是observer的接口類

/**
 * Created by 笑飛 on 2016/4/28.
 * 觀察者,需要應用觀察者模式時要實現此接口
 */
public interface Observer  {
    void onUpdate();
}

    其次是observer的實現類

/**
 * Created by 笑飛 on 2016/4/28.
 */
public class ConcreteObserver implements Observer {
   private String myOnlyAttr;
    private int changeCount;
    /*刷新自己*/
    @Override
    public void onUpdate() {
        myOnlyAttr = "通知Observer刷新了:"+(changeCount++)+"次";
    }

    public String getMyOnlyAttr() {
        return myOnlyAttr;
    }
}

  其次是subject的祖宗類

/**
 * Created by 笑飛 on 2016/4/28.
 * 發送者,需要應用觀察者模式時的被觀察者要繼承此類
 */
public abstract class Subject {
    /*將一個被觀察者對象和多個觀察者對象綁定起來*/
 protected List<Observer> observers = new ArrayList<>();
    /*添加觀察者,我們可能需要各種各樣的觀察者*/
    public void attachObserver(Observer observer){
        if (null ==observer){
            throw new NullPointerException();
        }
        if (!observers.contains(observer)){
            observers.add(observer);
        }
    }
    public void detachObserver(Observer observer){
         if (null ==observer){
             throw new NullPointerException();
         }
        if (observers.contains(observer)){
            observers.remove(observer);
        }
    }
    public abstract void notifyObserverUpdate();
}

其次是subject的實現類:

/**
 * Created by 笑飛 on 2016/4/28.
 * 實現了刷新方法
 */
public class ConcreteSubject extends Subject {
    @Override
    public void notifyObserverUpdate() {
        for (Observer observer :observers){
            observer.onUpdate();
        }
    }
}

然後是activity的測試部分

public class MainActivity extends AppCompatActivity {
    private ConcreteSubject subject;
    private TextView textView;
    ConcreteObserver observer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        observer = new ConcreteObserver();
        subject = new ConcreteSubject();
        /*綁定觀察者*/
        subject.attachObserver(observer);
    }
    public void update(View v){
        /*通知觀察者刷新*/
        subject.notifyObserverUpdate();
        textView.setText(observer.getMyOnlyAttr());
    }
}

    在開始第三部分之前,我們要注意,如果把上面的observer換成listview,把subject換成adapter,是不是我們經常看到和用到的listview的用法?其實 listview內置了observer,而adpter中內置了subject,換言之,listview和adapter其實就是觀察者與被觀察者的“形象代言人”。

   好了,接下啦讓我們以android中的經典ArrayAdapter來開始第三部分的分析吧!

   三、android中listview的具體實現

  • listview中的observer
 public void setAdapter(ListAdapter adapter) {

        if (null != mAdapter) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver); // 關鍵的成員變量,繼承自AbsListView,等下去看看AbsListView關於mDataSetObserver的內容
        }
        resetList();
        mRecycler.clear();
        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos,mFooterViewInfos, adapter);
        } else {
            mAdapter = adapter;
        }
        mOldSelectedPosition = INVALID_POSITION;
        mOldSelectedRowId = INVALID_ROW_ID;
        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
            checkFocus();
            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver); // 在這裡進行注冊,注冊為發送者adapter的觀察者
            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
            int position;
            if (mStackFromBottom) {
                position = lookForSelectablePosition(mItemCount - 1, false);
            } else {
                position = lookForSelectablePosition(0, true);
            }
            setSelectedPositionInt(position);
            setNextSelectedPositionInt(position);
            if (mItemCount == 0) {
                // Nothing selected
                checkSelectionChanged();
            }
            if (mChoiceMode != CHOICE_MODE_NONE &&
                    mAdapter.hasStableIds() &&
                    mCheckedIdStates == null) {
                mCheckedIdStates = new LongSparseArray<Boolean>();
            }
        } else {
            mAreAllItemsSelectable = true;
            checkFocus();
            // Nothing selected
            checkSelectionChanged();
        }
        if (mCheckStates != null) {
            mCheckStates.clear();
        }    
        if (mCheckedIdStates != null) {
            mCheckedIdStates.clear();
        }
        requestLayout();
}
}

     mDataSetObserver這個觀察者在AbsListView中:

AdapterDataSetObserver mDataSetObserver; // mDataSetObserver就是在這裡定義的。那我們再看看AdapterDataSetObserver是什麼類型的數據,看看當數據發生變化的時候,該類會進行什麼樣的動作。

   接下來去AdapterView中,發現AdapterDataSetObserver是其一個內部類:

class AdapterDataSetObserver extends DataSetObserver {
        private Parcelable mInstanceState = null;
        @Override
        public void onChanged() {
            mDataChanged = true;
            mOldItemCount = mItemCount;
            mItemCount = getAdapter().getCount();
            // Detect the case where a cursor that was previously invalidated has
            // been repopulated with new data.
            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null&& mOldItemCount == 0 && mItemCount > 0) {
                AdapterView.this.onRestoreInstanceState(mInstanceState);
                mInstanceState = null;
            } else {
                rememberSyncState();
            }
            checkFocus();
            requestLayout();  // 這裡是關鍵:這就是為什麼數據發生了變化,視圖可以隨之變換的原因,因為它會調用框架,來進行重新繪制。最終調用的代碼看緊接著的代碼
        }
        @Override
        public void onInvalidated() {
            mDataChanged = true;
            if (AdapterView.this.getAdapter().hasStableIds()) {
                // Remember the current state for the case where our hosting activity is being
                // stopped and later restarted
                mInstanceState = AdapterView.this.onSaveInstanceState();
            }
            // Data is invalid so we should reset our state
            mOldItemCount = mItemCount;
            mItemCount = 0;
            mSelectedPosition = INVALID_POSITION;
            mSelectedRowId = INVALID_ROW_ID;
            mNextSelectedPosition = INVALID_POSITION;
            mNextSelectedRowId = INVALID_ROW_ID;
            mNeedSync = false;
            checkSelectionChanged();
            checkFocus();
            requestLayout();
        }
        public void clearSavedState() {
            mInstanceState = null;
        }
    }
  •     ArrayAdapter中的subject(發送者,google大神命名為Observable,較為貼切)

          在ArrayAdapter中:

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();   // 關鍵代碼,這個notifyDataSetChanged()是從父類BaseAdapter繼承過來的,所以看看在父類中它干了些什麼
        mNotifyOnChange = true;
}

         然後在BaseAdapter中:

 private final DataSetObservable mDataSetObservable = new DataSetObservable();
//這對方法用來注冊或注銷從屬ArrayAdapter的觀察者,從此以後,adapter就成了發送者(Observable)的代理人 public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); } public void unregisterDataSetObserver(DataSetObserver observer) { mDataSetObservable.unregisterObserver(observer); }
public void notifyDataSetChanged() {
  mDataSetObservable.notifyChanged();  // 關鍵代碼:說明調的是成員變量mDataSetObservable的方法,所以進入DataSetObservable看看具體是如何操作的
}
 

       接下來看發送者和發送者的祖宗,是不是很熟悉了?請自行與第二部分的發送者對應:

public class DataSetObservable extends Observable<DataSetObserver> {
    /**
     * Invokes onChanged on each observer. Called when the data set being observed has
     * changed, and which when read contains the new state of the data.
     */
    public void notifyChanged() {
        synchronized(mObservers) {
            for (DataSetObserver observer : mObservers) { // 這裡的mObservers是哪來的呢?繼續追蹤,但首先可以判斷是來自Observable<DataSetObserver>的。進入看看
                observer.onChanged();
            }
        }
    }
    /**
     * Invokes onInvalidated on each observer. Called when the data set being monitored
     * has changed such that it is no longer valid.
     */
    public void notifyInvalidated() {
        synchronized (mObservers) {
            for (DataSetObserver observer : mObservers) {
                observer.onInvalidated();
            }
        }
    }
}
public abstract class Observable<T> {
    /**
     * The list of observers.  An observer can be in the list at most
     * once and will never be null.
     */
    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();
        }      
    }
}

總結:觀察者模式看起來很高大上,其實說白了就是一個類維護了另一個類的一個集合,並通過這個集合綁定解綁或調用另一個類的方法,只不過,在設計底層框架時候,利用了多態的特性抽象出了接口和抽象類,以便適用於各種場合。其實在做終端頁面時候完全用不到,因為多態只能增加運行時開銷。然而,設置一個龐大系統時候,這種設計模式在面向對象的編程語言,可謂不能不用的手段了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved