事件总线Otto源码解析

Otto 事件总线示例

Otto是发布订阅式框架。由Square开发,但是Square停止更新了,推荐用Rxjava来代替。还是来学习一下Otto的思想。

首先来看看示例,定义一个Otto管理类,封装Bus的注册、取消注册,向外提供这些方法:

   public class OttoBusManager {
    private static OttoBusManager instance;
    private Bus bus;

    public static OttoBusManager getInstance() {
        if (instance == null) {
            synchronized (OttoBusManager.class) {
                if (instance == null) {
                    instance = new OttoBusManager();
                }
            }
        }

        return instance;
    }

    private OttoBusManager() {
        bus = new Bus(ThreadEnforcer.ANY);
    }

    public void register(Object o) {
        bus.register(o);
    }

    public void unRegister(Object o) {
        bus.unregister(o);
    }
    public void notifyNotification(User user){
		bus.post(user);
	}
}

然后再看看事件发送者如何使用:

//创建时注册:
OttoBusManager.getInstance().register(this);

//销毁时注销:
OttoBusManager.getInstance().unRegister(this);
	 
//合适的地方发送通知:
OttoBusManager.getInstance().notifyNotification(new User());

//或者,给方法名添加注解
	@Produce
  Public BusData setInitialContent() {
        return new BusData("更新数据了");
 }
OttoBusManager.getInstance().notifyNotification(setInitialContent);
	 

再看看消息接受者:

//在需要发送事件的地方,创建时注册:
OttoBusManager.getInstance().register(this);
	 
//销毁时注销:
OttoBusManager.getInstance().unRegister(this);

//接受通知,接收通知的地方最好方法写成一样的,这样比较好找,其实方法名可以任意的,区分是参数:
      @Subscribe
    public void notifyBatteryChange(BatteryInfoBus bus) {
       //那么只要发送者发送了数据,接收者就可以收到了。
    }	

Otto源码解析

可从三个步骤来分析:

1.register()
2.bus.post()
3.unregister()

1.register() 源码

 public void register(Object object) {
    if (object == null) {
      throw new NullPointerException("Object to register must not be null.");
    }
	//用于控制Bus的线程的,可以指定是any或者Main Thread
    enforcer.enforce(this);

	//用于找到Object类里面标注了@Producer注解的方法,注意了,一个注册类只能有一个发布者,但是可以有多个接收者。
    Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
	
    for (Class<?> type : foundProducers.keySet()) {

      final EventProducer producer = foundProducers.get(type);
      EventProducer previousProducer = producersByType.putIfAbsent(type, producer);
      //checking if the previous producer existed
      if (previousProducer != null) {
        throw new IllegalArgumentException("Producer method for type " + type
          + " found on type " + producer.target.getClass()
          + ", but already registered by type " + previousProducer.target.getClass() + ".");
      }
      Set<EventHandler> handlers = handlersByType.get(type);
      if (handlers != null && !handlers.isEmpty()) {
        for (EventHandler handler : handlers) {
          dispatchProducerResultToHandler(handler, producer);
        }
      }
    }

	//一个注册类可以有多个接受者,看Map的value,是一个Set集合就明白了。
    Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object);
    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);
      if (!handlers.addAll(foundHandlers)) {
        throw new IllegalArgumentException("Object already registered.");
      }
    }

    for (Map.Entry<Class<?>, Set<EventHandler>> entry : foundHandlersMap.entrySet()) {
      Class<?> type = entry.getKey();
      EventProducer producer = producersByType.get(type);
      if (producer != null && producer.isValid()) {
        Set<EventHandler> foundHandlers = entry.getValue();
        for (EventHandler foundHandler : foundHandlers) {
          if (!producer.isValid()) {
            break;
          }
          if (foundHandler.isValid()) {
            dispatchProducerResultToHandler(foundHandler, producer);
          }
        }
      }
    }
  }

2.bus.post() 如何发送数据的过程。

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

	//找到订阅了该事件的所有class。
    Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());

    boolean dispatched = false;
    for (Class<?> eventType : dispatchTypes) {
		//遍历该class集合,找到对应的注册了该事件的方法,
      Set<EventHandler> wrappers = getHandlersForEventType(eventType);

      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();
  }

3. 取消注册

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

	//取消发布者,从缓存中拿到指定发布者,然后remove掉
    Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object);
    for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) {
      final Class<?> key = entry.getKey();
      EventProducer producer = getProducerForEventType(key);
      EventProducer value = entry.getValue();

      if (value == null || !value.equals(producer)) {
        throw new IllegalArgumentException(
            "Missing event producer for an annotated method. Is " + object.getClass()
                + " registered?");
      }
      producersByType.remove(key).invalidate();
    }

	//取消订阅者,方法一样。
    Map<Class<?>, Set<EventHandler>> handlersInListener = handlerFinder.findAllSubscribers(object);
    for (Map.Entry<Class<?>, Set<EventHandler>> entry : handlersInListener.entrySet()) {
      Set<EventHandler> currentHandlers = getHandlersForEventType(entry.getKey());
      Collection<EventHandler> eventMethodsInListener = entry.getValue();

      if (currentHandlers == null || !currentHandlers.containsAll(eventMethodsInListener)) {
        throw new IllegalArgumentException(
            "Missing event handler for an annotated method. Is " + object.getClass()
                + " registered?");
      }

      for (EventHandler handler : currentHandlers) {
        if (eventMethodsInListener.contains(handler)) {
          handler.invalidate();
        }
      }
      currentHandlers.removeAll(eventMethodsInListener);
    }
  }

这个框架其实很简单,将接受者注册到一个Map中,当发送者发送消息时,遍历Map,找到具体的接受者,然后调用它的接受方法即可。

猜你喜欢

转载自blog.csdn.net/qq_26984087/article/details/89406999