ZNDS智能电视网 推荐当贝市场

TV应用下载 / 资源分享区

软件下载 | 游戏 | 讨论 | 电视计算器

综合交流 / 评测 / 活动区

交流区 | 测硬件 | 网站活动 | Z币中心

新手入门 / 进阶 / 社区互助

新手 | 你问我答 | 免费刷机救砖 | ROM固件

查看: 9449|回复: 0
上一主题 下一主题
[教程]

Android 设计模式 之 观察者模式

[复制链接]
跳转到指定楼层
楼主
发表于 2013-8-28 16:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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   
  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();   
            }           
        }   
    }
复制代码
,实现的方法同Oberver一样,只不过它是通知ArrayList<Observer>下的每个Oberver去执行各自的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();   
                }   
            }   
        }   
    }
复制代码
,具体观察者的任务是实实在在执行action的类,一般由开发者根据实际情况,自己实现。android也有实现的例子源码路径: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关联了一个DataSetObservable对象,并实现registerDataSetObserver和unregisterDataSetObserver两个方法实现注册和撤销Observer,方法notifyDataSetChanged间接调用Observer的实现者的onChange()方法,以达到通知数据改变的作用。使用ListView和BaseAdapter组合时,当BaseAdapter的item改变时,我们经常会调用notifyDataSetChanged(),通知Listview刷新。但是,但是,但是,我们从来没有调用BaseAdapter的registerDataSetObserver(DataSetObserver observer)注册Observer,那么Listview如何接收到通知,并执行刷新动作呢?我们来看看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 课件共享
下一篇:【持续更新 - 8月17日】Android经典教程合集【申请转正贴】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|新帖|标签|软件|Sitemap|ZNDS智能电视网 ( 苏ICP备2023012627号 )

网络信息服务信用承诺书 | 增值电信业务经营许可证:苏B2-20221768 丨 苏公网安备 32011402011373号

GMT+8, 2024-5-2 20:36 , Processed in 0.063222 second(s), 15 queries , Redis On.

Powered by Discuz!

监督举报:report#znds.com (请将#替换为@)

© 2007-2024 ZNDS.Com

快速回复 返回顶部 返回列表