观察者模式

作者: Chauncey_Chen | 来源:发表于2017-01-05 14:46 被阅读40次

    观察者模式

    定义

    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    应用场景

    有一个事件发生改变,需要通知其他多个对象时.更多的应用于异步回调场景.

    代码实现

    UML类图结构

    代码实践

    1.Subject主题

    public class Subject {
        /**
         * 事件持有观察者的集合
         */
        private List<Observer> observers=new ArrayList<>();
        
        /**
         * 事件的状态
         */
        private String state;
        
        /**
         * 增加观察者
         */
        public void attach(Observer observer){
            
            observers.add(observer);
            
            
        }
        /**
         * 遍历通知观察者
         */
         public void notifyAllObservers(){
              for (Observer observer : observers) {
                 observer.update(state);
              }
           }
    
         
         
        public String getState() {
            return state;
        }
        /**
         * 当状态发生改变,通知观察者
         */
        public void setState(String state) {
            this.state = state;
            notifyAllObservers();
        }     
    
    }
    
    

    2.观察者接口

    public interface  Observer {
        /**
         * 更新观察者的状态
         */
        public void update(String state);
    
    }
    
    

    3.观察者具体实现

    public class Observer1 implements Observer {
    
        @Override
        public void update(String state) {
            // TODO Auto-generated method stub
            System.out.println("Observer1 update:"+state);
        }
    
    }
    
    

    4.测试

    
    public class Test {
    
        
        
        public static void main(String[] args) {
            
            //新建事件
            Subject subject=new Subject();
            //新建观察者
            Observer observer1=new Observer1();
            Observer observer2=new Observer2();
            //绑定观察者
            subject.attach(observer1);
            subject.attach(observer2);
            //更新事件状态
            subject.setState("我更新了");
    
        }
    }
    
    

    5.测试结果

    Observer1 update:我更新了
    Observer2 update:我更新了
    
    

    ListView中的观察者模式

    • 在adapter中有一个内部类AdapterDataSetObserver,这个就是一个观察者.

    • 在listView.setadapter时候会初始观察者.

    • 在AdapterDataSetObserver的onChanged函数中会获取Adapter中数据集的新数量,然后调用ListView的requestLayout()方法重新进行布局,更新用户界面。

    源码分析

    参考这是一篇关于listview源码的文章

    BaseAdapter 中notifyDataSetChanged 调用的mDataSetObservable.notifyChanged();

    public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
        // 数据集观察者,这里将观察者放到一个类中集中管理
        private final DataSetObservable mDataSetObservable = new DataSetObservable();
    
        public void registerDataSetObserver(DataSetObserver observer) {
            mDataSetObservable.registerObserver(observer);
        }
    
        public void unregisterDataSetObserver(DataSetObserver observer) {
            mDataSetObservable.unregisterObserver(observer);
        }
    
        /**
         * Notifies the attached observers that the underlying data has been changed
         * and any View reflecting the data set should refresh itself.
         * 当数据集用变化时通知所有观察者
         */
        public void notifyDataSetChanged() {
            mDataSetObservable.notifyChanged();
        }
    }
    
    

    在mDataSetObservable.notifyChanged()中遍历所有观察者,并且调用它们的onChanged方法。

    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) {
                // 调用所有观察者的onChanged方式
                for (int i = mObservers.size() - 1; i >= 0; i--) {
                    mObservers.get(i).onChanged();
                }
            }
        }
        ...
    }
    
    

    继承自AbsListView的父类AdapterView的AdapterDataSetObserver,

      class AdapterDataSetObserver extends DataSetObserver {
    
            private Parcelable mInstanceState = null;
            // 上文有说道,调用Adapter的notifyDataSetChanged的时候会调用所有观察者的onChanged方法,核心实现就在这里
            @Override
            public void onChanged() {
                mDataChanged = true;
                mOldItemCount = mItemCount;
                // 获取Adapter中数据的数量
                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();
                // 重新布局ListView、GridView等AdapterView组件
                requestLayout();
            }
    
            ...
    
            public void clearSavedState() {
                mInstanceState = null;
            }
    
    

    总结

    所谓观察者模式,就是

    多个观察者Observer -->观察attach--> 目标Subject的变化--->并通知刷新update

    相关文章

      网友评论

        本文标题:观察者模式

        本文链接:https://www.haomeiwen.com/subject/ykjzvttx.html