文章目录
EventBus 是一个事件发布/订阅框架,通过解耦发布者和订阅者简化 Android 事件传递,这里的事件可以理解为消息,本文中统一称为事件。事件传递既可用于 Android 四大组件间通讯,也可以用户异步线程和主线程间通讯等等。
EventBus简化了各组件间的通信,有效的分离事件发送方和接收方(也就是解耦的意思),避免复杂和容易出错的依赖性和生命周期问题。
类似于broadcastReceiver,EventBus比广播效率高。广播机制采用的观察者模式,即只要app注册了对广播的监听,广播发出的时候,就可以监听到。动态注册的广播必须动态取消。同样的,eventBus也需要注册和取消注册。
EventBus是按事件eventType来标记的,所有注册了,且标记了eventType的都会收到消息。
依赖引入:
compile 'org.greenrobot:eventbus:3.1.1'
在Activity 的onCreate() / onDestroy() 中分别register/unregister
EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);
//EventBus在合适的时机发出一个消息。可以任意定义消息
EventBus.getDefault().post(new AuthFailedMsg());
//在哪里进行接收处理呢?在刚刚注册、反注册的生命周期内可接收到消息并进行处理。
//可以指定threadMode、priority、sticky
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 10, sticky = false)
public void onAuthFailed(AuthFailedMsg msg) {
//身份过期, 清除用户缓存,跳转到登陆页面
Intent i = new Intent(this, LoginActivity.class);
startActivity(i);
}
总而言之:
- 在Activity的注册和反注册生命周期内,eventBus发出消息
- @subscriber注解标记的method如果入参和发出的消息类型匹配,即可进行消息的处理。
EventBus源码解析:
鉴于EventBus源码较少,所以全部铺开来看了。
@Subscriber可以标记threadMode、priority、sticky (priority数字越大,优先级最高)
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 10, sticky = false)
Sticky 事件不同之处在于,当事件发布后,再有订阅者开始订阅该类型事件,依然能收到该类型事件最近一个 Sticky 事件。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
boolean sticky() default false;
int priority() default 0;
}
1、获得EventBus实例
EventBus.getDefault(),单例模式(可保证同步),整个应用内只有一个实例。
//EventBus.java
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
subscriptionsByEventType = new HashMap<>(); //eventType对应的subscriptions
typesBySubscriber = new HashMap<>(); //subscriber对应的eventType
stickyEvents = new ConcurrentHashMap<>();
mainThreadSupport = builder.getMainThreadSupport();
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null; //主线程调度
backgroundPoster = new BackgroundPoster(this); //后台线程
asyncPoster = new AsyncPoster(this); //异步线程
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex); //注册的时候找订阅方法的
logSubscriberExceptions = builder.logSubscriberExceptions;
logNoSubscriberMessages = builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
throwSubscriberException = builder.throwSubscriberException;
eventInheritance = builder.eventInheritance;
executorService = builder.executorService;
}
EventBusBuilder.java
public class EventBusBuilder {
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
boolean logSubscriberExceptions = true;
boolean logNoSubscriberMessages = true;
boolean sendSubscriberExceptionEvent = true;
boolean sendNoSubscriberEvent = true;
boolean throwSubscriberException;
boolean eventInheritance = true;
boolean ignoreGeneratedIndex;
boolean strictMethodVerification;
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
List<Class<?>> skipMethodVerificationForClasses;
List<SubscriberInfoIndex> subscriberInfoIndexes;
Logger logger;
MainThreadSupport mainThreadSupport;
EventBusBuilder() {
}
}
2、register() 注册
public void register(Object subscriber) { //注册的是个对象
Class<?> subscriberClass = subscriber.getClass(); //得到注册对象的class,subscriberClass
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
SubscriberMethodFinder # findSubscriberMethods()
其实是加了一层缓存,CACHE_METHOD
private final boolean ignoreGeneratedIndex;
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//如果缓存里有就从缓存里取
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass); //通过反射的方式找subscriberMethods
} else {
subscriberMethods = findUsingInfo(subscriberClass); //通过APT
}
//如果subscriberMethods.isEmpty会报错
//也就是说注册的对象必须有通过@subscribe注解的有效方法
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else { // 存入缓存
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
2.1、SubscriberMethodFinder#findUsingReflection()
通过反射的方式得到List< SubscriberMethod>
- 准备一个FindState对象
- 初始化FindState对象
- 循环遍历,默认是可以向superClass一直找,直到findState.clazz为null
- 检查是否有通过@subscriber标记的有效方法
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState(); //准备一个FindState对象
findState.initForSubscriber(subscriberClass); //初始化FindState对象
while (findState.clazz != null) { //clazz为注册对象的类,也就是subscriberClass
findUsingReflectionInSingleClass(findState); //
findState.moveToSuperclass(); //默认是找父类,看是否有通过@subscriber标记的方法
}
return getMethodsAndRelease(findState);
}
SubscriberMethodFinder # prepareFindState()
如果FIND_STATE_POOL中有不为null的对象,取出来进行FindState对象的初始化。
private static final int POOL_SIZE = 4;
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();
}
SubscriberMethodFinder # findUsingReflectionInSingleClass()
- public Method[] getMethods():返回某个类、及其继承类(父类)、和所实现接口的所有公用方法。
- public Method[] getDeclaredMethods():返回某个类、和所实现接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承(父类)的任何方法。
定义Method数组,通过反射的方式拿到注册类subscribeClass的所有methods,且必须是public方法,non-static,non-abstract,有且只有一个入参,入参类型即为eventType,通过@subscribe注解标注。
如果此类中没有一个method满足这些条件,findState.moveToSuperClass()
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods; //定义Method数组
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true; //因为getMethods()里包含了继承的超类,所以接下来要跳过继承类
}
for (Method method : methods) { //遍历所有Method
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
如果此类中存在method满足这些条件,就进入到下面的分析
- findState.checkAdd(method, eventType)给anyMethodByEventType或者subscriberClassByMethodKey赋值
Class<?> eventType = parameterTypes[0]; //method的入参类型
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode(); //获取线程模式
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode,
int priority, boolean sticky) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
SubscriberMethodFinder # getMethodAndRelease()
-
也有可能findState.subscriberMethod里并没有对象,所以,但是会报错"Subscriber " + subscriberClass + " and its super classes have no public methods with the @Subscribe annotation"
-
这里有个小问题哈,为啥把使用完成的findState赋给缓冲池,下次从缓冲池里取出这个不为null的FindState进行复用呢?为什么不从缓冲池里取出一个null对象进行使用,然后使用完成后再赋null。
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle(); 初始化,清除引用
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState; //把使用完成的findState赋给缓冲池
break;
}
}
}
return subscriberMethods;
}
FindState是SubscriberMethodFinder的静态内部类
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class<?> subscriberClass;
Class<?> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass; //subscriberClass和clazz都为注册对象的类
skipSuperClasses = false; //默认为false
subscriberInfo = null; //默认为null
}
void recycle() { //初始化,清除引用
subscriberMethods.clear(); //subscriberMethods清空
anyMethodByEventType.clear(); //anyMethodByEventType清空
subscriberClassByMethodKey.clear(); //subscriberClassByMethodKey清空
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
//两级校对,一般来说,一个subscriberClass对同一个eventType只会做一次监听
//假如一个subscriberClass对同一个eventType做了多次监听,即一个类里通过@subscriber标记且入参类型相同的的方法有多个
boolean checkAdd(Method method, Class<?> eventType) { //传入method和method的入参类型
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true; //只做了一次监听,简简单单
} else {
if (existing instanceof Method) { //existing是通过@subscriber标记的旧方法
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType); //method是通过@subscriber标记的新方法
}
}
//给subscriberClassByMethodKey赋值("方法名>方法入参类型", 方法所属类的类对象methodClass)
//这意味着一个类如果使用了多个方法对同一个 Event 对象进行注册,那么当该 Event 对象被发送出来的时候,所有的方法都将会得到回调。
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0); //methodKeyBuilder是一个128位的StringBuilder
methodKeyBuilder.append(method.getName()); //方法名肯定唯一
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString(); //methodKey为"方法名>方法入参类型"
Class<?> methodClass = method.getDeclaringClass(); //得到方法所属类的类对象methodClass
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass); //
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
//当子类「显示」实现父类的订阅方法的时候,如果此时发射指定 Event的话,
//父类的订阅方法将不会执行,而仅会执行子类的订阅方法。
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
void moveToSuperclass() {
if (skipSuperClasses) { //初始化的时候默认为false
clazz = null; //清空clazz
} else {
clazz = clazz.getSuperclass(); //找subscribeClass的父类,
String clazzName = clazz.getName();
/** Skip system classes, this just degrades performance. */
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
clazz = null;
}
}
}
}
注册过程最终又回到:遍历subscriberMethods,
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber; //用于反注册,发送消息没用到
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) { //eventType对应的Subscription
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
int size = subscriptions.size();
for (int i = 0; i <= size; i++) { //按优先级倒序排列
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber); //subscriber对应的eventType
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
注册到这里算是结束了。
-
首先根据subscriber找到该类通过@Subscribe标记的所有SubscriberMethod
-
遍历所有的subscriberMethod
-
subscriptionsByEventType存入eventType和CopyOnWriteArrayList的对应关系,新的这个subscriberMethod封装成Subscription对象,按优先级存入CopyOnWriteArrayList中。消息类型 -> 订阅者/订阅方法
-
typesBySubscriber存入subscriber和List的对应关系,这个eventType添加到List。订阅者 -> 消息类型
3、unregister() 取消注册
-
typesBySubscriber 根据反注册对象subscriber找到List
-
遍历eventType,subscriptionsByEventType 根据eventType找到List
-
遍历subscription,如果subscription的subscriber和需要反注册的对象一致,则remove掉这个subscription。反注册对象对应的每个subscribeMethod去掉了。
-
最终remove掉这个typesBySubscriber中的subscriber。反注册对象也清掉了。
public synchronized void unregister(Object subscriber) {
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else { //如果根据订阅者没有找到订阅的消息类型,则没有注册过
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
4、post发送消息
PostingThreadState是EventBus中的静态内部类。
EventBus # post()
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<>(); //消息或者说事件队列
boolean isPosting; //是否在分发处理中
boolean isMainThread; //是否是主线程
Subscription subscription; //封装了subscriber和subscriberMethod
// (subscriberMethod又封装了method/eventType/threadMode/priority/sticky)
Object event; //事件
boolean canceled; //是否被取消
}
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get(); //
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event); //将要发送的event加入到PostingThreadState中的eventQueue中。
if (!postingState.isPosting) { //确保不会被调用多次
postingState.isMainThread = isMainThread(); //初始化postingState的isMainThread和isPosting
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false; //还原postingState的的isMainThread和isPosting
postingState.isMainThread = false;
}
}
}
EventBus # postSingleEvent()
eventInheritance:事件eventType之间是否存在继承关系,如果没有,可以设置为false
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
EventBus # postSingleEventForEventType()
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
subscriptions = subscriptionsByEventType.get(eventClass); //根据eventType得到subscriptions
}
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) { 遍历subscriptions,
postingState.event = event; //给postingState的event和subscription赋值
postingState.subscription = subscription;
boolean aborted = false;
try {
postToSubscription(subscription, event, postingState.isMainThread);
aborted = postingState.canceled;
} finally {
postingState.event = null; // 还原postingState的event和subscription状态
postingState.subscription = null;
postingState.canceled = false;
}
if (aborted) {
break;
}
}
return true;
}
return false;
}
EventBus # postToSubscription()
EventBus可以实现跨线程调度:需要注意的是,在主线程中不应该执行过多耗时操作
-
POSTING: 接收事件方法和发送事件方法在同一个线程中执行(由于发射事件方法线程可能是主线程,这意味着接收方法不能执行耗时操作,否则会阻塞主线程)
-
MAIN: 接收事件方法在主线程中执行,不管发送事件是在主线程还是子线程。如果发送事件是在主线程,则接收事件会立即执行,否则会被扔进 MessageQueue 中进行等待执行。
-
MAIN_ORDERED: 在 Android 中则接收事件方法会被扔进 MessageQueue 中等待执行(这意味着发射事件方法是不会被阻塞的)。
-
BACKGROUND: 如果是在主线程中发送事件,则接收事件方法应执行在子线程执行,但该子线程是 EventBus 维护的单一子线程,所以为了避免影响到其他接收事件方法的执行,该方法不应太耗时避免该子线程阻塞。
如果发送事件是在子线程中执行的,则接收事件与发送事件在同一个子线程中执行。 -
ASYNC: 接收事件和发送事件不在同一个线程中,且接收事件不会在子线程。常用于耗时操作,例如网络访问。当然,尽量避免在同一个时间大量触发此类型方法,尽管 EventBus 为此专门创建了线程池来管理回收利用这些线程。
public enum ThreadMode {
POSTING,
MAIN,
MAIN_ORDERED,
BACKGROUND,
ASYNC
}
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING: //在同一个线程中,直接执行
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) { //如果发送是在主线程,则直接执行
invokeSubscriber(subscription, event);
} else { //否则同mainThreadPoster进行线程调度
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber
invokeSubscriber(subscription, event);
}
break;
case BACKGROUND:
if (isMainThread) { //如果是在主线程中发送,则通过backgroundPoster进行线程调度
backgroundPoster.enqueue(subscription, event);
} else { //否则在这个子线程中直接执行(维护单一子线程)
invokeSubscriber(subscription, event);
}
break;
case ASYNC:
asyncPoster.enqueue(subscription, event); //始终在不一样的线程中
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
在FirstActivity的主线程中发送了一个消息,并对同一中EventType消息事件做了5次监听,指定不同线程
- Posting是在同一个线程中
- BACKGROUND维护单一子线程
- ASYNC每次都会创建不同线程
- thread.toString()打印出来的是线程名、优先级和线程组
在FirstActivity的子线程中发送了一个消息,并对同一种EventType消息事件做了5次监听,指定不同线程
- 如果发送事件已经是在子线程中,则直接执行
利用反射的方式直接执行
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active) {
invokeSubscriber(subscription, event);
}
}
void invokeSubscriber(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
5、Poster
最后来看看EventBus是怎么来实现线程调度的
mainThreadPoster、backgroundPoster、asyncPoster是在EventBus初始化的时候实例化的。
mainThreadPoster、backgroundPoster、asyncPoster都实现了Poster接口。
mainThreadPoster:
backgroundPoster:
asyncPoster:
interface Poster {
void enqueue(Subscription subscription, Object event);
}
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
5.1 BackgroundPoster
-
eventBus.getExecutorService() 是在EventBus实例化时初始化的,Executors.newCachedThreadPool()
-
前面我们说了BACKGROUND维护单一子线程,但是Executors.newCachedThreadPool()里维护的线程可以有Integer.MAX_VALUE个。
-
executorRunning是实现单一线程池的关键,volatile修饰,用作标志位,保证同一时刻只有一个线程处于运行状态
volatile保证可见性:
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
* 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了这个变量的值,这新值对其他线程来说是立即可见的。
* 禁止进行指令重排序。(有序性)
* 不能保证原子性
final class BackgroundPoster implements Runnable, Poster {
private final PendingPostQueue queue;
private final EventBus eventBus;
private volatile boolean executorRunning;
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue(); //EventBus实例化时,初始化
}
public void enqueue(Subscription subscription, Object event) { //实现的Poster接口
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
//从缓冲池取出一个pendingPost, 并给pendingPost的event和subscription赋值
synchronized (this) {
queue.enqueue(pendingPost); //将初始化完成的pendingPost入队
if (!executorRunning) {
executorRunning = true; //标记开始执行
eventBus.getExecutorService().execute(this); //线程池中执行当前runnable对象
}
}
}
@Override
public void run() {
try {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000);
//延时1s,从queue中取出一个pendingPost,不一定是刚入队的pendingPost
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost); //
}
} catch (InterruptedException e) {
eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
}
} finally {
executorRunning = false;
}
}
}
PendingPostQueue
PendingPostQueue是一个采用单链表实现的队列,先进先出,或者说后进后出。
final class PendingPostQueue {
private PendingPost head; //头指针
private PendingPost tail; //尾指针
synchronized void enqueue(PendingPost pendingPost) { //入队,尾部插入
if (pendingPost == null) {
throw new NullPointerException("null cannot be enqueued");
}
if (tail != null) {
tail.next = pendingPost;
tail = pendingPost;
} else if (head == null) {
head = tail = pendingPost;
} else {
throw new IllegalStateException("Head present, but no tail");
}
notifyAll();
}
synchronized PendingPost poll() { //出队,头部取出
PendingPost pendingPost = head;
if (head != null) {
head = head.next;
if (head == null) {
tail = null;
}
}
return pendingPost;
}
}
PendingPost
final class PendingPost {
private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>(); //static缓冲池
Object event;
Subscription subscription;
PendingPost next; //指向下一个节点
private PendingPost(Object event, Subscription subscription) { //构造函数初始化
this.event = event;
this.subscription = subscription;
}
static PendingPost obtainPendingPost(Subscription subscription, Object event) { // obtain
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
if (size > 0) {
PendingPost pendingPost = pendingPostPool.remove(size - 1); //取出最后一个PendingPost
pendingPost.event = event; //对pendingPost进行赋值
pendingPost.subscription = subscription;
pendingPost.next = null;
return pendingPost;
}
}
return new PendingPost(event, subscription);
}
static void releasePendingPost(PendingPost pendingPost) { //release
pendingPost.event = null;
pendingPost.subscription = null;
pendingPost.next = null;
synchronized (pendingPostPool) {
// Don't let the pool grow indefinitely
if (pendingPostPool.size() < 10000) {
pendingPostPool.add(pendingPost);
}
}
}
}
5.2 AsyncPoster
相比BackgroundPoster简单很多,最主要的区别就是少了一个volatile标记executorRunning
AsynPoster始终执行在一个新的子线程中,既区别于发送消息的线程,也区别于主线程
class AsyncPoster implements Runnable, Poster {
private final PendingPostQueue queue;
private final EventBus eventBus;
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
@Override
public void run() {
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
eventBus.invokeSubscriber(pendingPost);
}
}
5.3 mainThreadPoster
mainThreadPoster其实是HandlerPoster实现的,得到主线程的looper对象
然后通过这个主线程的handler进行主线程上消息的执行
public class HandlerPoster extends Handler implements Poster {
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper); // handler是主线程的handler
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) { //主线程的handler当然在主线程处理消息啦
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
取消事件的传递:
example:
TestAActivity和TestBActivity在onCreate和onDestroy内分别注册和反注册了EventBus。TestAActivity点击按钮启动TestBActivity,TestBActivity点击按钮发送一个Event事件,则TestAActivity和TestBActivity都能响应这个event事件(TestAActivity还没有执行到onDestroy())。
TestAActivity和TestBActivity都继承自BaseAcitivity,BaseActivity在onCreate和onDestroy内分别注册和反注册了EventBus。表现现象和上面一致()。
事件取消后就不会再传递
// Called in the same thread (default)
@Subscribe
public void onEvent(MessageEvent event){
// Process the event
…
EventBus.getDefault().cancelEventDelivery(event) ;
}
6、总结
-
使用上:就是注册register和反注册unRegister的生命周期内可以监听到post出的event事件。
-
实现上:
-
注册:把当前注册类的所有通过@subscriber标记的方法找出来;形成eventType和list的对应关系,并把不同或者相同eventType的subscription放入list中;subscription包含了subscriber和和subscriberMethod,subscriberMethod包含了method、eventType、threadMode、priority、sticky;形成注册类subscriber和eventType的对应关系。
-
反注册:把当前反注册类subscriber监听的所有eventType找出来,再根据eventType找到list,匹配subscription,如果subscriber和当前反注册的类相同,则remove掉。最终也移除掉反注册类和eventType的关系。
-
发送消息:根据eventType找到list,遍历每个subscription,进行事件消息分发调度。
参考: