android中的设计模式--观察者模式

“在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,一来它的对象都会收到通知”

场景:
某一个对象(或者数据)更新了,其他的一些类也要跟着变化,比如,在Android中,某个数据发生了改变,多处的UI要同时随之变化。

解决思路:
1.建立一个被监听的内容类(Observable),这个类实现一个接口,里面有三个主要方法,register,unregister,notifyObserver。

notifyObserver方法当监听对象发生变化时调用,把这个消息告诉所有的监听者(Observer)
register方法提供给Observer 这注册使用,Observer调用此方法后,就能收到notifyObserver传来的消息
unregister用来取消注册

2.所有的监听者实现Observer接口。该接口主要有一个update方法,当监听对象发生变化时,这个方法会被调用

public class Publisher implement Observable {
     
     //构建一个列表,里面放着所有订阅了这个监听对象的监听者的引用
     private ArrayList<Observer> observerList;     

     public Publisher() {
          observerList = new ArrayList<Observer>;
     }

     @Override
     public void register(Observer ob) {
          observerList.add(ob);     //注册其实就是把这个监听者的引用加入到上面那个队列里
     }

     @Override
     public void unregister(Observer ob) {
          int index = observerList.indexOf(o);
          if (index >= 0) {
               observerList.remove(index);
          }
     }
     
     //其实就是拿出上面那个list里的所有监听者,然后依次调用他们的update方法
     @Override
     public void notifyObserver() {
          for(int i = 0; i < observerList.size(); i++) {
               observerList.get(i).update;
          }
     }
}

public class Subscriber() implement Observer {
     
     private Publisher  publisher;
     
     //初始化的时候需要告诉监听者具体要监听谁
     public Subscriber(Publisher  publisher) {
          this.publisher = publisher;
          publisher.register(this);
     }     
     
     @Override
     public void update() {
          //收到消息后的处理
     }
}

在Android中的应用:Otto EventBus
Otto 是Android系统的一个Event Bus模式类库。用来简化应用组件间的通信Read more: http://blog.chengyunfeng.com/?p=450
Otto的用法:在组件的相关生命周期中通过Bus类的register 函数来注册,然后Bus类会扫描改类中带有@Produce和 @Subscribe 注解的函数。
@Subscribe 注解告诉Bus该函数订阅了一个事件,该事件的类型为该函数的参数类型;而@Produce注解告诉Bus该函数是一个事件产生者,产生的事件类型为该函数的返回值。
post方法用来发布一个事件

register方法:

1. 首先把这个页面的所有pushisher和Subscribers 全部遍历出来,我们重点看Subscriber, 遍历Subscribers的核心代码如下: 

 Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object);  //取出这个object里所有带subscribe装饰器的函数
    for (Class<?> type : foundHandlersMap.keySet()) {   //遍历这些函数
      Set<EventHandler> handlers = handlersByType.get(type);    //看看这些函数有没有已经被注册过
      if (handlers == null) {
        //concurrent put if absent
        Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();
        handlers = handlersByType.putIfAbsent(type, handlersCreation);
        if (handlers == null) {
            handlers = handlersCreation;
        }
      }
      final Set<EventHandler> foundHandlers = foundHandlersMap.get(type);
      handlers.addAll(foundHandlers);   //如果没有,就把这些函数放入handlersByType里,handlersByType就相当于标准实现里的observerList
    }

 

2.当一个新的消费发出时,会调用post方法:

public void post(Object event) {
    if (event == null) {
      throw new NullPointerException("Event to post must not be null.");
    }
    enforcer.enforce(this);

    Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());

    boolean dispatched = false;
    for (Class<?> eventType : dispatchTypes) {
      Set<EventHandler> wrappers = getHandlersForEventType(eventType); //从handlersByType里拿出相应的方法,这个是根据传进来的class类型来过滤的

      if (wrappers != null && !wrappers.isEmpty()) {
        dispatched = true;
        for (EventHandler wrapper : wrappers) {
          enqueueEvent(event, wrapper);
        }
      }
    }

    if (!dispatched && !(event instanceof DeadEvent)) {
      post(new DeadEvent(this, event));
    }

    dispatchQueuedEvents();
  }
     

 

猜你喜欢

转载自iam42.iteye.com/blog/2107058