Jcheng一霸 发表于 2013-8-28 16:27

Android 设计模式 之 观察者模式

4/*   
* 观察者模式   
*               定义对象间的一种一个(Subject)对多(Observer)的依赖关系,当一个对象的状态发送改变时,所以依赖于它的   
* 对象都得到通知并被自动更新   
*   
* 当然,MVC只是Observer模式的一个实例。Observer模式要解决的问题为:   
* 建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,   
* 依赖这个“一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析时候,   
* 我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。   
* 这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。   
* Observer模式就是解决了这一个问题。   
*   
* 适用性:   
*               1. 当一个抽象模型有两个方面,其中一个方面依赖于另一方面   
*               将这两者封装成独立的对象中以使它们可以各自独立的改变和服用   
*   
*               2. 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变   
*   
*               3. 当一个对象必须通知其它对象,而它又不能假定其它对象是谁   
*   
* 参与者:   
*               1. Subject(目标)   
*               目标知道它的观察者,可以有任意多个观察者观察同一个目标   
*               提供注册和删除观察者对象的接口   
*   
*               2. Observer(观察者)   
*               为那些在目标发生改变时需获得通知的对象定义个更新的接口   
*   
*               3. ConcreteSubject(具体目标)   
*               将有关状态存入各ConcreteObserver对象   
*               当它的状态发送改变时,向它的各个观察者发出通知   
*   
*               4. ConcreteObserver(具体观察者)   
*               维护一个指向ConcreteObserver对象的引用   
*               存储有关状态,这些状态应与目标的状态保持一致   
*               实现Observer的更新接口是自身状态与目标的状态保持一致   
*                  
*   
* */   
   
下面看看Android使用到的观察者模式.观察者(DataSetObserver),目标(Observable<T>),具体目标(DataSetObserverable),DataSetObserver抽象2个方法,一个是观察数据改变的方法,一个是观察数据变成无效(或者不可用)时的方法。源码路径:framework/base/core/java/android/database/DataSetObserver.java    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    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();   
      }         
    }   
},实现的方法同Oberver一样,只不过它是通知ArrayList<Observer>下的每个Oberver去执行各自的action。源码路径:framework/base/core/java/android/database/DataSetObservable.java    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();   
            }   
      }   
    }   
},具体观察者的任务是实实在在执行action的类,一般由开发者根据实际情况,自己实现。android也有实现的例子源码路径:framework/base/core/java/android/widget/AbsListView.java        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        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关联了一个DataSetObservable对象,并实现registerDataSetObserver和unregisterDataSetObserver两个方法实现注册和撤销Observer,方法notifyDataSetChanged间接调用Observer的实现者的onChange()方法,以达到通知数据改变的作用。使用ListView和BaseAdapter组合时,当BaseAdapter的item改变时,我们经常会调用notifyDataSetChanged(),通知Listview刷新。但是,但是,但是,我们从来没有调用BaseAdapter的registerDataSetObserver(DataSetObserver observer)注册Observer,那么Listview如何接收到通知,并执行刷新动作呢?我们来看看ListView做了什么        /**   
   * 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行                mAdapter = adapter;                mDataSetObserver = new AdapterDataSetObserver();   
            mAdapter.registerDataSetObserver(mDataSetObserver);</div
页: [1]
查看完整版本: Android 设计模式 之 观察者模式