Android事件总线框架Otto源码解析一(Bus的构造过程及在使用注解@Subscribe时的注册过程)

本文深入解析Android事件总线框架Otto的工作原理,通过示例代码详细分析Bus的构造、register方法执行流程及事件订阅机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 说明:本文的解析过程并不只是简单的讲解框架中各个方法的调用逻辑、程序的执行过程,而是依赖于示例代码,结合了具体的的示例程序的执行流程,有助于更好的理解。

有关Otto的使用方法参见另一篇文章: Android事件总线框架Otto使用介绍

package com.example.myotto;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.squareup.otto.Subscribe;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private Button mBtnJumpToPost, mBtnJumpToProduce, mBtnJumpToMainActivity;
    private TextView mTvMessage, mTvMessageUpdate;

    public static void start(Context context) {
        context.startActivity(new Intent(context, MainActivity.class));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTvMessage = (TextView) this.findViewById(R.id.tv_message);
        mTvMessageUpdate = (TextView) this.findViewById(R.id.tv_message_update);
        mBtnJumpToPost = (Button) this.findViewById(R.id.btn_jump_to_post);
        mBtnJumpToMainActivity = (Button) this.findViewById(R.id.btn_jump_to_main_activity);
        mBtnJumpToProduce = (Button) this.findViewById(R.id.btn_jump_to_produce);
        mBtnJumpToPost.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PostActivity.start(MainActivity.this);
            }
        });
        mBtnJumpToProduce.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ProduceActivity.start(MainActivity.this);
            }
        });
        mBtnJumpToMainActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity.start(MainActivity.this);
            }
        });
        Log.i(TAG, "method:onCreate#this#hashCode=" + this.hashCode());
        OttoBus.getInstance().register(this);
    }

    @Subscribe
    public void refreshMessage(EventData eventData) {
        Log.i(TAG, "method:Subscribe#refreshMessage#eventData#hashCode=" + eventData.hashCode());
        Log.i(TAG, "method:Subscribe#refreshMessage#eventData=" + eventData);
        mTvMessage.setText(eventData.getUserName() + ":\n\n" + eventData.getMessage());
    }

    @Subscribe
    public void updateMessage(EventData eventData) {
        Log.i(TAG, "method:updateMessage#updateMessage#eventData#hashCode=" + eventData.hashCode());
        Log.i(TAG, "method:Subscribe#updateMessage#eventData=" + eventData);
        mTvMessageUpdate.setText(eventData.getUserName() + ":\n\n" + eventData.getMessage());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        OttoBus.getInstance().unregister(this);
    }
}

 Bus的构造过程:

Otto源码中并没有提供Bus的单例实现,我们可以在使用前自行构造一个单例模式。

package com.example.myotto;

import com.squareup.otto.Bus;

public class OttoBus extends Bus {
    private volatile static OttoBus bus;

    private OttoBus() {
    }

    public static OttoBus getInstance() {
        if (bus == null) {
            synchronized (OttoBus.class) {
                if (bus == null) {
                    bus = new OttoBus();
                }
            }
        }
        return bus;
    }
}

在源码中Bus类的无参构造方法,实际上最终还是调用了 Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder)这个构造方法,并且在调用过程中注入了一些默认的参数 :DEFAULT_IDENTIFIER 、 ThreadEnforcer.MAIN 和HandlerFinder.ANNOTATED。

public class Bus {

  public static final String DEFAULT_IDENTIFIER = "default";

  /** All registered event handlers, indexed by event type. */
  private final ConcurrentMap<Class<?>, Set<EventHandler>> handlersByType =
          new ConcurrentHashMap<Class<?>, Set<EventHandler>>();

  /** All registered event producers, index by event type. */
  private final ConcurrentMap<Class<?>, EventProducer> producersByType =
          new ConcurrentHashMap<Class<?>, EventProducer>();

  /** Identifier used to differentiate the event bus instance. */
  private final String identifier;

  /** Thread enforcer for register, unregister, and posting events. */
  private final ThreadEnforcer enforcer;

  /** Used to find handler methods in register and unregister. */
  private final HandlerFinder handlerFinder;

  /** Queues of events for the current thread to dispatch. */
  private final ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>> eventsToDispatch =
      new ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>>() {
        @Override protected ConcurrentLinkedQueue<EventWithHandler> initialValue() {
          return new ConcurrentLinkedQueue<EventWithHandler>();
        }
      };

  /** True if the current thread is currently dispatching an event. */
  private final ThreadLocal<Boolean> isDispatching = new ThreadLocal<Boolean>() {
    @Override protected Boolean initialValue() {
      return false;
    }
  };

  public Bus() {
    this(DEFAULT_IDENTIFIER);
  }

  public Bus(String identifier) {
    this(ThreadEnforcer.MAIN, identifier);
  }

  public Bus(ThreadEnforcer enforcer) {
    this(enforcer, DEFAULT_IDENTIFIER);
  }

  public Bus(ThreadEnforcer enforcer, String identifier) {
    this(enforcer, identifier, HandlerFinder.ANNOTATED);
  }

  Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder) {
    this.enforcer =  enforcer;
    this.identifier = identifier;
    this.handlerFinder = handlerFinder;
  }

  .......省略.......

}

根据具体的示例分析 Bus 的 register(Object object) 方法在MainActivity的执行过程:

public class Bus{

  .......省略.......

 public void register(Object object) {
    if (object == null) {
      throw new NullPointerException("Object to register must not be null.");
    }
    // 检查线程,如果不是对应的线程则抛异常;默认的构造方法里使用的是主线程;
    // enforcer 就是构造过程中注入的默认参数 ThreadEnforcer.MAIN;
    // 它是 ThreadEnforcer 的一个实例,实现的 enforce(Bus bus)方法里会进行线程检查
    enforcer.enforce(this);  // 1

    // handlerFinder 就是构造过程中注入的默认参数 HandlerFinder.ANNOTATED;
    // 它是 HandlerFinder 的一个实例,实现了两个方法:findAllProducers(Object listener) 和 findAllSubscribers(Object listener);
    // findAllProducers(Object listener) 内部调用了 AnnotatedHandlerFinder 的 findAllProducers(Object listener);
    // 因为 MainActivity 中并没有 @Produce 的注解方法,所以这里返回的map大小是0,相关的逻辑也不再执行,接下来程序就会执行 handlerFinder.findAllSubscribers(object)方法;
    Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object); // 2
   .......省略.......

    // handlerFinder 就是构造过程中注入的默认参数 HandlerFinder.ANNOTATED;
    // findAllSubscribers(Object listener) 内部调用了 AnnotatedHandlerFinder 的 findAllSubscribers(Object listener);
    // 这里返回的map是;
    Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object);  // 3
    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);
          }
        }
      }
    }
  }

  .......省略.......

}

标注1处,即ThreadEnforcer类的处理逻辑:

public interface ThreadEnforcer {

  void enforce(Bus bus);

  ThreadEnforcer ANY = new ThreadEnforcer() {
    @Override public void enforce(Bus bus) {
      // Allow any thread.
    }
  };

  ThreadEnforcer MAIN = new ThreadEnforcer() {
    @Override public void enforce(Bus bus) {
      if (Looper.myLooper() != Looper.getMainLooper()) {
        throw new IllegalStateException("Event bus " + bus + " accessed from non-main thread " + Looper.myLooper());
      }
    }
  };

}

HandlerFinder类的具体处理逻辑:

interface HandlerFinder {

  Map<Class<?>, EventProducer> findAllProducers(Object listener);

  Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener);


  HandlerFinder ANNOTATED = new HandlerFinder() {
    @Override
    public Map<Class<?>, EventProducer> findAllProducers(Object listener) {
      return AnnotatedHandlerFinder.findAllProducers(listener);
    }

    @Override
    public Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {
      return AnnotatedHandlerFinder.findAllSubscribers(listener);
    }
  };
}

标注2处具体调用的方法:

final class AnnotatedHandlerFinder {

  /** Cache event bus producer methods for each class. */
  private static final ConcurrentMap<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE =
    new ConcurrentHashMap<Class<?>, Map<Class<?>, Method>>();

  /** Cache event bus subscriber methods for each class. */
  private static final ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE =
    new ConcurrentHashMap<Class<?>, Map<Class<?>, Set<Method>>>();

  .......省略..........

  /** This implementation finds all methods marked with a {@link Produce} annotation. */
  static Map<Class<?>, EventProducer> findAllProducers(Object listener) { 
    // listener 就是示例代码中的 MainActivity 的实例对象
    // 
    final Class<?> listenerClass = listener.getClass();
    Map<Class<?>, EventProducer> handlersInMethod = new HashMap<Class<?>, EventProducer>();

    // 此时缓存中还没有,methods集合为null;
    Map<Class<?>, Method> methods = PRODUCERS_CACHE.get(listenerClass);
    if (null == methods) {
      methods = new HashMap<Class<?>, Method>();
      loadAnnotatedProducerMethods(listenerClass, methods);
    }
    // 因为当前MainActivity里只有Subject注解的方法,所在这个集合大小是0;
    if (!methods.isEmpty()) {
      for (Map.Entry<Class<?>, Method> e : methods.entrySet()) {
        EventProducer producer = new EventProducer(listener, e.getValue());
        handlersInMethod.put(e.getKey(), producer);
      }
    }
    // 当前这个返回结果集合大小是0;
    return handlersInMethod;
  }

  .......省略..........

}

 loadAnnotatedProducerMethods(Class<?> listenerClass, Map<Class<?>, Method> producerMethods) 方法,最终调用loadAnnotatedMethods(Class<?> listenerClass,
      Map<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods) 这个方法

.......省略.........

 private static void loadAnnotatedProducerMethods(Class<?> listenerClass,
      Map<Class<?>, Method> producerMethods) {
    Map<Class<?>, Set<Method>> subscriberMethods = new HashMap<Class<?>, Set<Method>>();
    loadAnnotatedMethods(listenerClass, producerMethods, subscriberMethods);
  }


  /**
   * Load all methods annotated with {@link Produce} or {@link Subscribe} into their respective caches for the
   * specified class.
   */
  private static void loadAnnotatedMethods(Class<?> listenerClass,
      Map<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods) { // 传入的参数: 图1
    for (Method method : listenerClass.getDeclaredMethods()) {
      // The compiler sometimes creates synthetic bridge methods as part of the
      // type erasure process. As of JDK8 these methods now include the same
      // annotations as the original declarations. They should be ignored for
      // subscribe/produce.
      // 如果桥接方法,则不处理
      if (method.isBridge()) {
        continue;
      }
      // 判断方法是否以@Subscribe为注解
      if (method.isAnnotationPresent(Subscribe.class)) {
        Class<?>[] parameterTypes = method.getParameterTypes();
        // 方法的参数类型的数量只能有1个,否则抛出异常
        if (parameterTypes.length != 1) {
          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation but requires "
              + parameterTypes.length + " arguments.  Methods must require a single argument.");
        }

        Class<?> eventType = parameterTypes[0];
        if (eventType.isInterface()) {
          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
              + " which is an interface.  Subscription must be on a concrete class type.");
        }
         // 方法的访问修饰符必须是public;
        if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
                  + " but is not 'public'.");
        }

        Set<Method> methods = subscriberMethods.get(eventType);
        if (methods == null) {
          methods = new HashSet<Method>();
          subscriberMethods.put(eventType, methods);
        }
        methods.add(method);
      // 判断方法是否以@Produce为注解
      } else if (method.isAnnotationPresent(Produce.class)) {
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes.length != 0) {
          throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires "
              + parameterTypes.length + " arguments.  Methods must require zero arguments.");
        }
         // 方法的必须要有返回参数;
        if (method.getReturnType() == Void.class) {
          throw new IllegalArgumentException("Method " + method
              + " has a return type of void.  Must declare a non-void type.");
        }

        Class<?> eventType = method.getReturnType();
        if (eventType.isInterface()) {
          throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
              + " which is an interface.  Producers must return a concrete class type.");
        }
        if (eventType.equals(Void.TYPE)) {
          throw new IllegalArgumentException("Method " + method + " has @Produce annotation but has no return type.");
        }
        // 方法的访问修饰符必须是public;
        if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
          throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
              + " but is not 'public'.");
        }

        if (producerMethods.containsKey(eventType)) {
          throw new IllegalArgumentException("Producer for type " + eventType + " has already been registered.");
        }
        producerMethods.put(eventType, method);
      }
    }

    PRODUCERS_CACHE.put(listenerClass, producerMethods);
    SUBSCRIBERS_CACHE.put(listenerClass, subscriberMethods);
  }

.......省略.........

图1:

当查找到第一个以 Subscribe 为注解的 refreshMessage(EventData eventData)方法时,数据的处理流程:

1、判断参数个数

2、判断参数类型是否是接口类型

3、保存到对应的集合中

当查找到第二个以 Subscribe 为注解的 updateMessage(EventData eventData)方法时,数据的处理流程:

查找完所有以 Subscribe 为注解的方法后,再缓存入这个集合中:

总结一下上述方法中出现的集合存储的数据类型:

Map<Class<?>, Set<Method>> subscriberMethods 集合存入的数据类型:

key 是 EventData 的Class对象

value 是Set<Method>集合,比如:refreshMessage(EventData eventData)方法 和 updateMessage(EventData eventData)方法;

ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE 集合存入的数据可以是:

key 是 MainActivity 的Class对象

value 是 subscriberMethods 集合;

 标注3处最终调用的方法:

final class AnnotatedHandlerFinder {

  /** Cache event bus producer methods for each class. */
  private static final ConcurrentMap<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE =
    new ConcurrentHashMap<Class<?>, Map<Class<?>, Method>>();

  /** Cache event bus subscriber methods for each class. */
  private static final ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE =
    new ConcurrentHashMap<Class<?>, Map<Class<?>, Set<Method>>>();

  .......省略..........

 /** This implementation finds all methods marked with a {@link Subscribe} annotation. */
  static Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {
    Class<?> listenerClass = listener.getClass(); 
    Map<Class<?>, Set<EventHandler>> handlersInMethod = new HashMap<Class<?>, Set<EventHandler>>();
    // 此时缓存中已经有数据,如果没有,最终还会调用上述的查找所有Subscribe注解的方法
    Map<Class<?>, Set<Method>> methods = SUBSCRIBERS_CACHE.get(listenerClass);
    if (null == methods) {
      methods = new HashMap<Class<?>, Set<Method>>();
      loadAnnotatedSubscriberMethods(listenerClass, methods);
    }
    if (!methods.isEmpty()) {
      // 遍历这个集合,将数据封装到EventHandler的对象中,然后存入Map<Class<?>, Set<EventHandler>>集合中
      for (Map.Entry<Class<?>, Set<Method>> e : methods.entrySet()) {
        Set<EventHandler> handlers = new HashSet<EventHandler>();
        for (Method m : e.getValue()) {
          handlers.add(new EventHandler(listener, m));
        }
        handlersInMethod.put(e.getKey(), handlers);
      }
    }

    return handlersInMethod;
  }

  .......省略..........

}

总结一下这段代码执行完之后的数据情况:

循环遍历了集合 Map<Class<?>, Set<Method>> subscriberMethods 集合存入的数据可以是:

key 是 EventData 的Class对象

value 是Set<Method>集合,比如:refreshMessage(EventData eventData)方法 和 updateMessage(EventData eventData)方法

找到每一个key下对应的Set<Method>集合,然后遍历这个集合,将相应数据封装到 EventHandler 对象中,并且存入Set<EventHandler > 集合中,里层循环结束后,再将数据存入 Map<Class<?>, Set<EventHandler>> handlersInMethod 集合中;

EventHandler 对象创建时注入的参数 new EventHandler(listener, m);listener 是 MainActivity的Class对象,m 是 Subscribe注释方法 refreshMessage(EventData eventData)方法;

 Map<Class<?>, Set<EventHandler>> handlersInMethod 集合的 key 是 EventData 的Class对象,value 是 Set<EventHandler > 集合;

 下面我们回到Bus里标注3的返回结果:

public class Bus{

  .......省略.......

 public void register(Object object) {
   
   .......省略.......

   Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object); // 3
    for (Class<?> type : foundHandlersMap.keySet()) {
      // 此时handlersByType集合还是0,查找出的结果集合还是null;
      Set<EventHandler> handlers = handlersByType.get(type);
      if (handlers == null) {
        //concurrent put if absent
        Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();
        // 此时key对应的value还不存在,此方法会添加key和value,并且返回null
        handlers = handlersByType.putIfAbsent(type, handlersCreation);
        if (handlers == null) {
            // 将 CopyOnWriteArraySet类型的集合对象 handlersCreation 赋值给 handlers
            handlers = handlersCreation;
        }
      }
      final Set<EventHandler> foundHandlers = foundHandlersMap.get(type);
      // 如果Set集合发生更改,则返回true。
      if (!handlers.addAll(foundHandlers)) {
        throw new IllegalArgumentException("Object already registered.");
      }
    }

  .......省略.......

}

总结一下数据情况:

ConcurrentMap<Class<?>, Set<EventHandler>> handlersByType 的 key 是 EventData 的Class对象,value 是 Set<EventHandler > 集合;

到此注册方法的执行流程已经完成。

示例代码GitHub地址

由于作者水平有限,语言描述及代码实现中难免有纰漏,望各位看官多提宝贵意见!

Hello , World !

感谢所有!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

windfallsheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值