首頁 收藏 QQ群
 網(wǎng)站導航

ZNDS智能電視網(wǎng) 推薦當貝市場

TV應用下載 / 資源分享區(qū)

軟件下載 | 游戲 | 討論 | 電視計算器

綜合交流 / 評測 / 活動區(qū)

交流區(qū) | 測硬件 | 網(wǎng)站活動 | Z幣中心

新手入門 / 進階 / 社區(qū)互助

新手 | 你問我答 | 免費刷機救磚 | ROM固件

查看: 10748|回復: 0
上一主題 下一主題
[教程]

Android 設計模式 之 觀察者模式

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2013-8-28 16:27 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
4/*   
* 觀察者模式   
*                 定義對象間的一種一個(Subject)對多(Observer)的依賴關(guān)系,當一個對象的狀態(tài)發(fā)送改變時,所以依賴于它的   
* 對象都得到通知并被自動更新   
*   
* 當然,MVC只是Observer模式的一個實例。Observer模式要解決的問題為:   
* 建立一個一(Subject)對多(Observer)的依賴關(guān)系,并且做到當“一”變化的時候,   
* 依賴這個“一”的多也能夠同步改變。最常見的一個例子就是:對同一組數(shù)據(jù)進行統(tǒng)計分析時候,   
* 我們希望能夠提供多種形式的表示(例如以表格進行統(tǒng)計顯示、柱狀圖統(tǒng)計顯示、百分比統(tǒng)計顯示等)。   
* 這些表示都依賴于同一組數(shù)據(jù),我們當然需要當數(shù)據(jù)改變的時候,所有的統(tǒng)計的顯示都能夠同時改變。   
* Observer模式就是解決了這一個問題。   
*   
* 適用性:   
*                 1. 當一個抽象模型有兩個方面,其中一個方面依賴于另一方面   
*                 將這兩者封裝成獨立的對象中以使它們可以各自獨立的改變和服用   
*   
*                 2. 當對一個對象的改變需要同時改變其他對象,而不知道具體有多少對象有待改變   
*   
*                 3. 當一個對象必須通知其它對象,而它又不能假定其它對象是誰   
*   
* 參與者:   
*                 1. Subject(目標)   
*                 目標知道它的觀察者,可以有任意多個觀察者觀察同一個目標   
*                 提供注冊和刪除觀察者對象的接口   
*   
*                 2. Observer(觀察者)   
*                 為那些在目標發(fā)生改變時需獲得通知的對象定義個更新的接口   
*   
*                 3. ConcreteSubject(具體目標)   
*                 將有關(guān)狀態(tài)存入各ConcreteObserver對象   
*                 當它的狀態(tài)發(fā)送改變時,向它的各個觀察者發(fā)出通知   
*   
*                 4. ConcreteObserver(具體觀察者)   
*                 維護一個指向ConcreteObserver對象的引用   
*                 存儲有關(guān)狀態(tài),這些狀態(tài)應與目標的狀態(tài)保持一致   
*                 實現(xiàn)Observer的更新接口是自身狀態(tài)與目標的狀態(tài)保持一致   
*                    
*   
* */   
   
下面看看Android使用到的觀察者模式.觀察者(DataSetObserver),目標(Observable<T>),具體目標(DataSetObserverable),DataSetObserver抽象2個方法,一個是觀察數(shù)據(jù)改變的方法,一個是觀察數(shù)據(jù)變成無效(或者不可用)時的方法。源碼路徑:framework/base/core/java/android/database/DataSetObserver.java   
  1. package android.database;   
       
    /**   
    * Receives call backs when a data set has been changed, or made invalid. The typically data sets   
    * that are observed are {@link Cursor}s or {@link android.widget.Adapter}s.   
    * DataSetObserver must be implemented by objects which are added to a DataSetObservable.   
    */   
    public abstract class DataSetObserver {   
        /**   
         * This method is called when the entire data set has changed,   
         * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.   
         */   
        public void onChanged() {   
            // Do nothing   
        }   
       
        /**   
         * This method is called when the entire data becomes invalid,   
         * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a   
         * {@link Cursor}.   
         */   
        public void onInvalidated() {   
            // Do nothing   
        }   
    }
復制代碼
,Observable<T>是一個泛型的抽象類,主要功能是注冊和撤銷observer。源碼路徑:framework/base/core/java/android/database/Observable.java   
  1. package android.database;   
       
    import java.util.ArrayList;   
       
    /**   
    * Provides methods for (un)registering arbitrary observers in an ArrayList.   
    */   
    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>();   
       
        /**   
         * Adds an observer to the list. The observer cannot be null and it must not already   
         * be registered.   
         * @param observer the observer to register   
         * @throws IllegalArgumentException the observer is null   
         * @throws IllegalStateException the observer is already registered   
         */   
        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);   
            }   
        }   
       
        /**   
         * Removes a previously registered observer. The observer must not be null and it   
         * must already have been registered.   
         * @param observer the observer to unregister   
         * @throws IllegalArgumentException the observer is null   
         * @throws IllegalStateException the observer is not yet registered   
         */   
        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);   
            }   
        }   
          
        /**   
         * Remove all registered observer   
         */   
        public void unregisterAll() {   
            synchronized(mObservers) {   
                mObservers.clear();   
            }           
        }   
    }
復制代碼
,實現(xiàn)的方法同Oberver一樣,只不過它是通知ArrayList<Observer>下的每個Oberver去執(zhí)行各自的action。源碼路徑:framework/base/core/java/android/database/DataSetObservable.java   
  1. package android.database;   
       
    /**   
    * A specialization of Observable for DataSetObserver that provides methods for   
    * invoking the various callback methods of DataSetObserver.   
    */   
    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) {   
                // since onChanged() is implemented by the app, it could do anything, including   
                // removing itself from {@link mObservers} - and that could cause problems if   
                // an iterator is used on the ArrayList {@link mObservers}.   
                // to avoid such problems, just march thru the list in the reverse order.   
                for (int i = mObservers.size() - 1; i >= 0; i--) {   
                    mObservers.get(i).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 (int i = mObservers.size() - 1; i >= 0; i--) {   
                    mObservers.get(i).onInvalidated();   
                }   
            }   
        }   
    }
復制代碼
,具體觀察者的任務是實實在在執(zhí)行action的類,一般由開發(fā)者根據(jù)實際情況,自己實現(xiàn)。android也有實現(xiàn)的例子源碼路徑:framework/base/core/java/android/widget/AbsListView.java   
  1.     class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {   
            @Override   
            public void onChanged() {   
                super.onChanged();   
                if (mFastScroller != null) {   
                    mFastScroller.onSectionsChanged();   
                }   
            }   
       
            @Override   
            public void onInvalidated() {   
                super.onInvalidated();   
                if (mFastScroller != null) {   
                    mFastScroller.onSectionsChanged();   
                }   
            }   
        }
復制代碼
framework/base/core/java/android/widget/AdapterView.java
   
  1.     class AdapterDataSetObserver extends DataSetObserver {   
       
            private Parcelable mInstanceState = null;   
       
            @Override   
            public void onChanged() {   
                mDataChanged = true;   
                mOldItemCount = mItemCount;   
                mItemCount = getAdapter().getCount();   
                if (DBG) {   
                    Xlog.d(TAG, "AdapterView onChanged: mOldItemCount = " + mOldItemCount   
                            + ",mItemCount = " + mItemCount + ",getAdapter() = " + getAdapter()   
                            + ",AdapterView = " + AdapterView.this, new Throwable("onChanged"));   
                }   
       
                // 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 (DBG) {   
                    Xlog.d(TAG, "AdapterView onInvalidated: mOldItemCount = " + mOldItemCount   
                            + ",mItemCount = " + mItemCount + ",getAdapter() = " + getAdapter()   
                            + ",AdapterView = " + AdapterView.this, new Throwable("onInvalidated"));   
                }   
       
                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;   
       
                checkFocus();   
                requestLayout();   
            }   
       
            public void clearSavedState() {   
                mInstanceState = null;   
            }   
        }
復制代碼
  
型運用是大家熟悉的BaseAdapter,BaseAdapter關(guān)聯(lián)了一個DataSetObservable對象,并實現(xiàn)registerDataSetObserver和unregisterDataSetObserver兩個方法實現(xiàn)注冊和撤銷Observer,方法notifyDataSetChanged間接調(diào)用Observer的實現(xiàn)者的onChange()方法,以達到通知數(shù)據(jù)改變的作用。使用ListView和BaseAdapter組合時,當BaseAdapter的item改變時,我們經(jīng)常會調(diào)用notifyDataSetChanged(),通知Listview刷新。但是,但是,但是,我們從來沒有調(diào)用BaseAdapter的registerDataSetObserver(DataSetObserver observer)注冊Observer,那么Listview如何接收到通知,并執(zhí)行刷新動作呢?我們來看看ListView做了什么   
  1.     /**   
         * Sets the data behind this ListView.   
         *   
         * The adapter passed to this method may be wrapped by a {@link WrapperListAdapter},   
         * depending on the ListView features currently in use. For instance, adding   
         * headers and/or footers will cause the adapter to be wrapped.   
         *   
         * @param adapter The ListAdapter which is responsible for maintaining the   
         *        data backing this list and for producing a view to represent an   
         *        item in that data set.   
         *   
         * @see #getAdapter()   
         */   
        @Override   
        public void setAdapter(ListAdapter adapter) {   
            if (mAdapter != null && mDataSetObserver != null) {   
                mAdapter.unregisterDataSetObserver(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;   
       
            // AbsListView#setAdapter will update choice mode states.   
            super.setAdapter(adapter);   
       
            if (mAdapter != null) {   
                mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();   
                mOldItemCount = mItemCount;   
                mItemCount = mAdapter.getCount();   
                checkFocus();   
       
                mDataSetObserver = new AdapterDataSetObserver();   
                mAdapter.registerDataSetObserver(mDataSetObserver);   
       
                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();   
                }   
            } else {   
                mAreAllItemsSelectable = true;   
                checkFocus();   
                // Nothing selected   
                checkSelectionChanged();   
            }   
       
            requestLayout();   
        }
復制代碼
注意下面3行
   
  1.             mAdapter = adapter;
復制代碼
  
  1.             mDataSetObserver = new AdapterDataSetObserver();   
                mAdapter.registerDataSetObserver(mDataSetObserver);
復制代碼
</div

上一篇:Data Storage +AMS 課件共享
下一篇:【持續(xù)更新 - 8月17日】Android經(jīng)典教程合集【申請轉(zhuǎn)正貼】
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

Archiver|新帖|標簽|軟件|Sitemap|ZNDS智能電視網(wǎng) ( 蘇ICP備2023012627號 )

網(wǎng)絡信息服務信用承諾書 | 增值電信業(yè)務經(jīng)營許可證:蘇B2-20221768 丨 蘇公網(wǎng)安備 32011402011373號

GMT+8, 2024-10-19 16:20 , Processed in 0.065056 second(s), 15 queries , Redis On.

Powered by Discuz!

監(jiān)督舉報:report#znds.com (請將#替換為@)

© 2007-2024 ZNDS.Com

快速回復 返回頂部 返回列表