“在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,一来它的对象都会收到通知”
场景:
某一个对象(或者数据)更新了,其他的一些类也要跟着变化,比如,在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(); }