zoukankan      html  css  js  c++  java
  • 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();
            }      
        }
    }

    总结:观察者模式看起来很高大上,其实说白了就是一个类维护了另一个类的一个集合,并通过这个集合绑定解绑或调用另一个类的方法,只不过,在设计底层框架时候,利用了多态的特性抽象出了接口和抽象类,以便适用于各种场合。其实在做终端页面时候完全用不到,因为多态只能增加运行时开销。然而,设置一个庞大系统时候,这种设计模式在面向对象的编程语言,可谓不能不用的手段了。

  • 相关阅读:
    node.js中的全局变量——global
    Element-UI库 源码架构浅析
    如何搭建一个自己cli
    webpack实践之DLLPlugin 和 DLLReferencePlugin
    HappyPack优化
    线程和进程
    kafka?kafaka! kafka...
    Dubbo的初步理解和使用
    Redis的安装和启动
    解析Spring MVC上传文件
  • 原文地址:https://www.cnblogs.com/gangmiangongjue/p/5443459.html
Copyright © 2011-2022 走看看