EventBus原理源码分析和使用


转载自:http://blog.csdn.net/hua631150873/article/details/51377131


关于EventBus的原理,但我确实使用过,用起来也方便简单,一个注册,一个Post就能通知到所有的订阅者Subcriber,其实明明是知道一点点原理的,但是当时就是支支吾吾没有说,太low了,回来大概看了一眼EventBus的源码及实现原谅,现在想把看原代码的一些心得进行记录。OK,我们从Github上面了解一下官方如何介绍这个EventBus吧。


翻译:EventBus是一个事件发布/订阅总线,有效适用于Android系统平台。 
EventBus... 
.组件之间的通信更加简单 
。针对在事件的发送者和订阅者之间进行解耦 
。非常好的运用在Activitys、Fragments和后台线程 
。避开了联系紧密易出错的依赖关系和容易出错生命周期 
.使你的代码更加简洁 
.快 
.瘦(小于50K的jar包) 
.有100,00,000+的app使用了EventBus

简单翻译就是这样一个意思,翻译不好请多担待,但是尽管翻译很差,但是大体的原理描述和工作是体现出来了。我是直接从Github上下载的最新的源代码进行研究的,在这里我想提出一个注意的地方,之前的旧一点的版本3.0之前的版本,订阅者的事件通知的方法都是通过开发者遵守命名约定,这样没有安全性,容易出错,很不方便开发,但是后来3.0开始使用注解的方式对事件的方法的声明。如下是之前的版本使用的命名约定的方式。
1、onEvent
2、onEventMainThread
3、onEventBackgroundThread
4、onEventAsync
现在最新版本订阅者的事件方法名称可以随意声明,只要在方法的上简单的加上一些相关的注解就可以了,而且注解是必须加上的,否则会抛出Runtime异常。OK,看看我们现在的做法:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. </pre><pre code_snippet_id="1679566" snippet_file_name="blog_20160511_1_5619972" name="code" class="java">import org.greenrobot.eventbus.EventBus;  
  2. public class MainActivity extends Activity implements OnClickListener {  
  3.     private Button mButton;  
  4.         @Override  
  5.         protected void onCreate(Bundle savedInstanceState) {  
  6.             super.onCreate(savedInstanceState);  
  7.             setContentView(R.layout.main_layout);  
  8.             final Intent  intent= new Intent(this,EventBusTestService.class);  
  9.             startService(intent);  
  10.             EventBus.getDefault().register(this);  
  11.             mButton = (Button) findViewById(R.id.button1);  
  12.             mButton.setOnClickListener(this);  
  13.         }  
  14.   
  15.         @Subscribe(threadMode=ThreadMode.ASYNC)  
  16.         public void onEventReceive(EventBusMsg msg){  
  17.             Log.d("ZHG-EventBusTest","MainActivity.onEventReceive , msg = "+msg.msg +" , MainThreadID = "+this.getMainLooper().getThread().getId()+" , currentTreadID = "+Thread.currentThread().getId());  
  18.         }  
  19.   
  20.         @Override  
  21.         public void onClick(View view) {  
  22.                 switch (view.getId() ) {  
  23.                 case R.id.button1:  
  24.              EventBus.getDefault().post(new EventBusMsg("Test Message!!!!"));  
  25.                     break;  
  26.                 default:  
  27.                     break;  
  28.                 }  
  29.         }  
  30.   
  31.         @Override  
  32.         protected void onDestroy() {  
  33.             super.onDestroy();  
  34.             EventBus.getDefault().unregister(this);  
  35.         }  
  36. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.example.eventbustest;  
  2. import org.greenrobot.eventbus.EventBus;  
  3. public class EventBusTestService extends Service {  
  4.     @Override  
  5.     public IBinder onBind(Intent arg0) {  
  6.         return null;  
  7.     }  
  8.   
  9.     @Override  
  10.     public void onCreate() {  
  11.         super.onCreate();  
  12.         EventBus.getDefault().register(this);  
  13.     }  
  14.   
  15.     @Override  
  16.     public void onDestroy() {  
  17.         super.onDestroy();  
  18.         EventBus.getDefault().unregister(this);  
  19.     }  
  20.   
  21.     @Subscribe(threadMode=ThreadMode.BACKGROUND)  
  22.     public void onEventBusMsgReceive(EventBusMsg msg){  
  23.         Log.d("ZHG-EventBusTest","EventBusTestService.onEventBusMsgReceive , msg = "+msg.msg +" , MainThreadID = "+this.getMainLooper().getThread().getId()+" , currentTreadID = "+Thread.currentThread().getId());  
  24.     }  
  25. }  

从上面的示例代码就能看出,最新的版本再也不用那么麻烦的去记住什么约定的方法怎么写,不用再去背了,现在只要自己命名成自己喜欢的方法名,然后简单的加上注解就行,而且还可以设置线程模式,比如是是否在主线程、子线程、是否异步等。

OK,上面是针对使用上的一些变化进行一个温馨提示,接下来直接奔入主题,看源代码把。

1. EventBus.getDefault();开始
入口EventBus.getDefault();开始,这里我还是很喜欢这样的静态单例对象获取方法名,我本人也很喜欢使用单例的时候,取名getDefault()。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** Convenience singleton for apps using a process-wide EventBus instance. */  
  2.     public static EventBus getDefault() {  
  3.         if (defaultInstance == null) {  
  4.             synchronized (EventBus.class) {  
  5.                 if (defaultInstance == null) {  
  6.                     defaultInstance = new EventBus();  
  7.                 }  
  8.             }  
  9.         }  
  10.         return defaultInstance;  
  11.     }  

很简单,就是一个单例设计代码,看看构造方法。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.     * Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a 
  3.     * central bus, consider {@link #getDefault()}. 
  4.     */  
  5.    public EventBus() {  
  6.        this(DEFAULT_BUILDER);  
  7.    }  
  8.   
  9.    EventBus(EventBusBuilder builder) {  
  10.        subscriptionsByEventType = new HashMap<>();  
  11.        typesBySubscriber = new HashMap<>();  
  12.        stickyEvents = new ConcurrentHashMap<>();  
  13.        mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);  
  14.        backgroundPoster = new BackgroundPoster(this);  
  15.        asyncPoster = new AsyncPoster(this);  
  16.        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;  
  17.        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,  
  18.                builder.strictMethodVerification, builder.ignoreGeneratedIndex);  
  19.        logSubscriberExceptions = builder.logSubscriberExceptions;  
  20.        logNoSubscriberMessages = builder.logNoSubscriberMessages;  
  21.        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;  
  22.        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;  
  23.        throwSubscriberException = builder.throwSubscriberException;  
  24.        eventInheritance = builder.eventInheritance;  
  25.        executorService = builder.executorService;  
  26.    }  
构造方法中创建了几个容器,用来装各种订阅者信息的,很关键的几个成员我们需要注意,mainThreadPoster 、backgroundPoster 、asyncPoster ,这个几个是后来post消息的时候,用的到的,就是利用他们将消息在不同的线程发送出去,达到在不同线程中执行的效果。
mainThreadPoster:很显然是一个自定义扩展后的Handler,在构造的时候传入的是主线的Looper,所以它是一个主线程的对应的Handler。
这里之间先看看这个Handler的代码吧:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.  * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)  
  2. package org.greenrobot.eventbus;  
  3.   
  4. import android.os.Handler;  
  5.   
  6. final class HandlerPoster extends Handler {  
  7.   
  8.     private final PendingPostQueue queue;  
  9.     private final int maxMillisInsideHandleMessage;  
  10.     private final EventBus eventBus;  
  11.     private boolean handlerActive;  
  12.   
  13.     HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {  
  14.         super(looper);  
  15.         this.eventBus = eventBus;  
  16.         this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;  
  17.         queue = new PendingPostQueue();  
  18.     }  
  19.   
  20.     void enqueue(Subscription subscription, Object event) {  
  21.         PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);  
  22.         synchronized (this) {  
  23.             queue.enqueue(pendingPost);  
  24.             if (!handlerActive) {  
  25.                 handlerActive = true;  
  26.                 if (!sendMessage(obtainMessage())) {  
  27.                     throw new EventBusException("Could not send handler message");  
  28.                 }  
  29.             }  
  30.         }  
  31.     }  
  32.   
  33.     @Override  
  34.     public void handleMessage(Message msg) {  
  35.         boolean rescheduled = false;  
  36.         try {  
  37.             long started = SystemClock.uptimeMillis();  
  38.             while (true) {  
  39.                 PendingPost pendingPost = queue.poll();  
  40.                 if (pendingPost == null) {  
  41.                     synchronized (this) {  
  42.                         // Check again, this time in synchronized  
  43.                         pendingPost = queue.poll();  
  44.                         if (pendingPost == null) {  
  45.                             handlerActive = false;  
  46.                             return;  
  47.                         }  
  48.                     }  
  49.                 }  
  50.                 eventBus.invokeSubscriber(pendingPost);  
  51.                 long timeInMethod = SystemClock.uptimeMillis() - started;  
  52.                 if (timeInMethod >= maxMillisInsideHandleMessage) {  
  53.                     if (!sendMessage(obtainMessage())) {  
  54.                         throw new EventBusException("Could not send handler message");  
  55.                     }  
  56.                     rescheduled = true;  
  57.                     return;  
  58.                 }  
  59.             }  
  60.         } finally {  
  61.             handlerActive = rescheduled;  
  62.         }  
  63.     }  
  64. }   

没错,就是传入一个MainThread的Looper,创建了一个主线程的Handler,毋庸置疑,通过他发送的事件消息,都是在主线中执行的。

backgroundPoster : 那这个是什么呢,我们来看看代码。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.  * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)  
  2. package org.greenrobot.eventbus;  
  3.   
  4. import android.util.Log;  
  5.   
  6. /** 
  7.  * Posts events in background. 
  8.  *  
  9.  * @author Markus 
  10.  */  
  11. final class BackgroundPoster implements Runnable {  
  12.   
  13.     private final PendingPostQueue queue;  
  14.     private final EventBus eventBus;  
  15.   
  16.     private volatile boolean executorRunning;  
  17.   
  18.     BackgroundPoster(EventBus eventBus) {  
  19.         this.eventBus = eventBus;  
  20.         queue = new PendingPostQueue();  
  21.     }  
  22.   
  23.     public void enqueue(Subscription subscription, Object event) {  
  24.         PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);  
  25.         synchronized (this) {  
  26.             queue.enqueue(pendingPost);  
  27.             if (!executorRunning) {  
  28.                 executorRunning = true;  
  29.                 eventBus.getExecutorService().execute(this);  
  30.             }  
  31.         }  
  32.     }  
  33.   
  34.     @Override  
  35.     public void run() {  
  36.         try {  
  37.             try {  
  38.                 while (true) {  
  39.                     PendingPost pendingPost = queue.poll(1000);  
  40.                     if (pendingPost == null) {  
  41.                         synchronized (this) {  
  42.                             // Check again, this time in synchronized  
  43.                             pendingPost = queue.poll();  
  44.                             if (pendingPost == null) {  
  45.                                 executorRunning = false;  
  46.                                 return;  
  47.                             }  
  48.                         }  
  49.                     }  
  50.                     eventBus.invokeSubscriber(pendingPost);  
  51.                 }  
  52.             } catch (InterruptedException e) {  
  53.                 Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);  
  54.             }  
  55.         } finally {  
  56.             executorRunning = false;  
  57.         }  
  58.     }  
  59. }  
很明显他是一个实现了Runnable 的对象,所以它的载体肯定是一个子线程,是给某子线程执行具体任务的。

asyncPoster :再来看看这个,这个听名字就感觉已经知晓大部分信息了,异步Poster,可定也是在单独线程中post任务的。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)  
  2. package org.greenrobot.eventbus;  
  3.   
  4.   
  5. /** 
  6.  * Posts events in background. 
  7.  *  
  8.  * @author Markus 
  9.  */  
  10. class AsyncPoster implements Runnable {  
  11.   
  12.     private final PendingPostQueue queue;  
  13.     private final EventBus eventBus;  
  14.   
  15.     AsyncPoster(EventBus eventBus) {  
  16.         this.eventBus = eventBus;  
  17.         queue = new PendingPostQueue();  
  18.     }  
  19.   
  20.     public void enqueue(Subscription subscription, Object event) {  
  21.         PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);  
  22.         queue.enqueue(pendingPost);  
  23.         eventBus.getExecutorService().execute(this);  
  24.     }  
  25.   
  26.     @Override  
  27.     public void run() {  
  28.         PendingPost pendingPost = queue.poll();  
  29.         if(pendingPost == null) {  
  30.             throw new IllegalStateException("No pending post available");  
  31.         }  
  32.         eventBus.invokeSubscriber(pendingPost);  
  33.     }  
  34. }  
所以这里就不用多说了,也是一个实现了Runnable 的对象,一定也是被子线程执行的具体任务。

所以最后我们都能看到上面三段代码两个共同的两行代码:
eventBus.invokeSubscriber(pendingPost);  这行代码其实就是在使用反射调用订阅的者的事件方法。
 eventBus.getExecutorService().execute(this); 这行代码很明显就是把时间提交给一个空闲的线程去执行。
当然HandlerPoster 就除外了,当然他是使用sendMessage的方式去去执行一个具体的事件,其实对应的也是 eventBus.getExecutorService().execute(this);这行代码。

OK,这里我们就浅层次的分析到这里,我们回到主线,继续。


2.register(Object subcriber)注册订阅者

我们通过EventBus的getDefualt()方法获取了一个EventBus的对象,然后就可以通过他来注册地订阅者了,接下来就看看EventBus的register(Object subcriber)方法是如果实现的呢?
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.     * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they 
  3.     * are no longer interested in receiving events. 
  4.     * <p/> 
  5.     * Subscribers have event handling methods that must be annotated by {@link Subscribe}. 
  6.     * The {@link Subscribe} annotation also allows configuration like {@link 
  7.     * ThreadMode} and priority. 
  8.     */  
  9.    public void register(Object subscriber) {  
  10.        Class<?> subscriberClass = subscriber.getClass();  
  11.        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);  
  12.        synchronized (this) {  
  13.            for (SubscriberMethod subscriberMethod : subscriberMethods) {  
  14.                subscribe(subscriber, subscriberMethod);  
  15.            }  
  16.        }  
  17.    }  

OK,从上面的代码中,我们可以看到调用了 subscriberMethodFinder对象的findSubscriberMethods(subscriberClass);方法,subscriberMethodFinder这个对象呢,我们其实都不用太关心,可以把他当作一个管理获取、查找、订阅者和订阅者Method的对象,然后通过它我们就能拿到一个List集合,这个集合存储的都是SubscriberMehtod对象,这里有必要去追求一下SubscriberMehtod是个什么东西呢,我们来看看吧:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.  * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)  
  2. package org.greenrobot.eventbus;  
  3.   
  4. import java.lang.reflect.Method;  
  5.   
  6. /** Used internally by EventBus and generated subscriber indexes. */  
  7. public class SubscriberMethod {  
  8.     final Method method;  
  9.     final ThreadMode threadMode;  
  10.     final Class<?> eventType;  
  11.     final int priority;  
  12.     final boolean sticky;  
  13.     /** Used for efficient comparison */  
  14.     String methodString;  
  15.   
  16.     public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {  
  17.         this.method = method;  
  18.         this.threadMode = threadMode;  
  19.         this.eventType = eventType;  
  20.         this.priority = priority;  
  21.         this.sticky = sticky;  
  22.     }  
  23.   
  24.     @Override  
  25.     public boolean equals(Object other) {  
  26.         if (other == this) {  
  27.             return true;  
  28.         } else if (other instanceof SubscriberMethod) {  
  29.             checkMethodString();  
  30.             SubscriberMethod otherSubscriberMethod = (SubscriberMethod)other;  
  31.             otherSubscriberMethod.checkMethodString();  
  32.             return methodString.equals(otherSubscriberMethod.methodString);  
  33.         } else {  
  34.             return false;  
  35.         }  
  36.     }  
  37.   
  38.     private synchronized void checkMethodString() {  
  39.         if (methodString == null) {  
  40.             // Method.toString has more overhead, just take relevant parts of the method  
  41.             StringBuilder builder = new StringBuilder(64);  
  42.             builder.append(method.getDeclaringClass().getName());  
  43.             builder.append('#').append(method.getName());  
  44.             builder.append('(').append(eventType.getName());  
  45.             methodString = builder.toString();  
  46.         }  
  47.     }  
  48.   
  49.     @Override  
  50.     public int hashCode() {  
  51.         return method.hashCode();  
  52.     }  
  53. }  
很明显从这个SubscriberMethod 类的成员变量就能看出来,这是一个封装了一个关于Method的信息的对象,这些信息包括   final Method method(反射方法对象)对象、 final ThreadMode threadMode(线程模式)对象、final Class<?> eventType(事件类型,方法中的参数)对象、final int priority(权限) 标记、  final boolean sticky(是否sticky类型)标记、 String methodString(方法描述字串) 用来提高两个SubscriberMethod对象比较效率和准确性的。
所以这类就这么简单,就是封装了一个Mehtod的全部信息的。

接下来代码主线往下走。
我们来看一下findSubscriberMethods方法,是如何获取到订阅者的所有方法信息的,直接看方法。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {  
  2.        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);  
  3.        if (subscriberMethods != null) {  
  4.            return subscriberMethods;  
  5.        }  
  6.        if (ignoreGeneratedIndex) {  
  7.            subscriberMethods = findUsingReflection(subscriberClass);  
  8.        } else {  
  9.            subscriberMethods = findUsingInfo(subscriberClass);  
  10.        }  
  11.        if (subscriberMethods.isEmpty()) {  
  12.            throw new EventBusException("Subscriber " + subscriberClass+ " and its super classes have no public methods with the @Subscribe annotation");  
  13.        } else {  
  14.            METHOD_CACHE.put(subscriberClass, subscriberMethods);  
  15.            return subscriberMethods;  
  16.        }  
  17.    }  

从上面的代码可以看的出,一开始 METHOD_CACHE这个集合是空的,获取的时候为空,逻辑会往下走,ignoreGeneratedIndex经过打印默认初始是为false的,所以下一步会走subscriberMethods = findUsingInfo(subscriberClass); OK,直接来看findUsingInfo(subscriberClass);方法。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {  
  2.       FindState findState = prepareFindState();  
  3.       findState.initForSubscriber(subscriberClass);  
  4.       while (findState.clazz != null) {  
  5.           findState.subscriberInfo = getSubscriberInfo(findState);  
  6.           if (findState.subscriberInfo != null) {  
  7.               SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();  
  8.               for (SubscriberMethod subscriberMethod : array) {  
  9.                   if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {  
  10.                       findState.subscriberMethods.add(subscriberMethod);  
  11.                   }  
  12.               }  
  13.           } else {  
  14.               findUsingReflectionInSingleClass(findState);  
  15.           }  
  16.           findState.moveToSuperclass();  
  17.       }  
  18.       return getMethodsAndRelease(findState);  
  19.   }  
 findState.subscriberInfo = getSubscriberInfo(findState); 根据打印,获取到的为null,
所以会走   findUsingReflectionInSingleClass(findState);我们也来看看这个方法的实现。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void findUsingReflectionInSingleClass(FindState findState) {  
  2.         Method[] methods;  
  3.         try {  
  4. // This is faster than getMethods, especially when subscribers are fat classes like Activities  
  5.             methods = findState.clazz.getDeclaredMethods();  
  6.         } catch (Throwable th) {  
  7.             methods = findState.clazz.getMethods();  
  8.             findState.skipSuperClasses = true;  
  9.         }  
  10.         for (Method method : methods) {  
  11.             int modifiers = method.getModifiers();  
  12.      if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {  
  13.                 Class<?>[] parameterTypes = method.getParameterTypes();  
  14.                 if (parameterTypes.length == 1) {  
  15.                     Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);  
  16.                     if (subscribeAnnotation != null) {  
  17.                         Class<?> eventType = parameterTypes[0];  
  18.                         if (findState.checkAdd(method, eventType)) {  
  19.                             ThreadMode threadMode = subscribeAnnotation.threadMode();  
  20.                             findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,  
  21.                                     subscribeAnnotation.priority(), subscribeAnnotation.sticky()));  
  22.                         }  
  23.                     }  
  24.                 } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {  
  25.                     String methodName = method.getDeclaringClass().getName() + "." + method.getName();  
  26.                     throw new EventBusException("@Subscribe method " + methodName +  
  27.                             "must have exactly 1 parameter but has " + parameterTypes.length);  
  28.                 }  
  29.             } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {  
  30.                 String methodName = method.getDeclaringClass().getName() + "." + method.getName();  
  31.                 throw new EventBusException(methodName +  
  32.                         " is a illegal @Subscribe method: must be public, non-static, and non-abstract");  
  33.             }  
  34.         }  
  35.     }  
所以通过上面的代码,很明显就可以看出,是通过反射拿到每一个方法的修饰符信息,注解信息,参数信息,从上面的代码很明显就知道,我们的订阅方法必须有且只有一个参数,否则会抛出异常的,而且订阅方法必须是public修饰的,而且不是静态、不是抽象方法,否者也会抛出异常的,最后将合法的订阅方法都存到了一个 findState.subscriberMethods集合中了,最后在findUsingReflectionInSingleClass(findState);的调用方发处调用了  
return getMethodsAndRelease(findState);返回了出去了一个 List<SubscriberMethod>集合,这里需要稍微提醒一个地方就是,我们应该都发现了findUsingInfo(Class<?> subscriberClass) 方法中的倒数第四行findState.moveToSuperclass(); 看看这个方法吧.

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void moveToSuperclass() {  
  2.             if (skipSuperClasses) {  
  3.                 clazz = null;  
  4.             } else {  
  5.                 clazz = clazz.getSuperclass();  
  6.                 String clazzName = clazz.getName();  
  7.                 /** Skip system classes, this just degrades performance. */  
  8.                 if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {  
  9.                     clazz = null;  
  10.                 }  
  11.             }  
  12.         }  

这个方法主要是获取当前Class对象的父类(有可能是抽象类或者接口),这样在findUsingInfo(Class<?> subscriberClass) 方法while中循环的获取到每一级Class对象中所有方法信息。

OK,findSubscriberMethods(...)方法就分析到这里,主线接着往下走,回到register方法中,往下看。

然后我们能看到一个for循环的遍历。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. synchronized (this) {  
  2.            for (SubscriberMethod subscriberMethod : subscriberMethods) {  
  3.                subscribe(subscriber, subscriberMethod);  
  4.            }  
  5.        }  

遍历每一个SubscriberMethod对象,遍历到每一个SubscriberMethod对象之后,调用EventBus的  subscribe(subscriber, subscriberMethod); 方法,那我们就直接来看这个方法。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.  // Must be called in synchronized block  
  2.     private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {  
  3.         Class<?> eventType = subscriberMethod.eventType;  
  4.         Subscription newSubscription = new Subscription(subscriber, subscriberMethod);  
  5.         CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);  
  6.         if (subscriptions == null) {  
  7.             subscriptions = new CopyOnWriteArrayList<>();  
  8.             subscriptionsByEventType.put(eventType, subscriptions);  
  9.         } else {  
  10.             if (subscriptions.contains(newSubscription)) {  
  11.                 throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "+ eventType);  
  12.             }  
  13.         }  
  14.   
  15.         int size = subscriptions.size();  
  16.         for (int i = 0; i <= size; i++) {  
  17.             if (i == size || subscriberMethod.priority >   
  18. subscriptions.get(i).subscriberMethod.priority) {  
  19.                 subscriptions.add(i, newSubscription);  
  20.                 break;  
  21.             }  
  22.         }  
  23.   
  24.         List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);  
  25.         if (subscribedEvents == null) {  
  26.             subscribedEvents = new ArrayList<>();  
  27.             typesBySubscriber.put(subscriber, subscribedEvents);  
  28.         }  
  29.         subscribedEvents.add(eventType);  
  30.   
  31.         if (subscriberMethod.sticky) {  
  32.             if (eventInheritance) {  
  33.                 // Existing sticky events of all subclasses of eventType have to be considered.  
  34.                 // Note: Iterating over all events may be inefficient with lots of sticky events,  
  35.                 // thus data structure should be changed to allow a more efficient lookup  
  36.                 // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).  
  37.                 Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();  
  38.                 for (Map.Entry<Class<?>, Object> entry : entries) {  
  39.                     Class<?> candidateEventType = entry.getKey();  
  40.                     if (eventType.isAssignableFrom(candidateEventType)) {  
  41.                         Object stickyEvent = entry.getValue();  
  42.                         checkPostStickyEventToSubscription(newSubscription, stickyEvent);  
  43.                     }  
  44.                 }  
  45.             } else {  
  46.                 Object stickyEvent = stickyEvents.get(eventType);  
  47.                 checkPostStickyEventToSubscription(newSubscription, stickyEvent);  
  48.             }  
  49.         }  
  50.     }  

一开始就取出了eventType,然后就创建了一个Subscription对象,这里又需要解释一下这个对象是个什么玩意了,直接贴代码吧。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.  * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)  
  2. package org.greenrobot.eventbus;  
  3.   
  4. final class Subscription {  
  5.     final Object subscriber;  
  6.     final SubscriberMethod subscriberMethod;  
  7.     /** 
  8.      * Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery 
  9.      * {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions. 
  10.      */  
  11.     volatile boolean active;  
  12.   
  13.     Subscription(Object subscriber, SubscriberMethod subscriberMethod) {  
  14.         this.subscriber = subscriber;  
  15.         this.subscriberMethod = subscriberMethod;  
  16.         active = true;  
  17.     }  
  18.   
  19.     @Override  
  20.     public boolean equals(Object other) {  
  21.         if (other instanceof Subscription) {  
  22.             Subscription otherSubscription = (Subscription) other;  
  23.             return subscriber == otherSubscription.subscriber  
  24.                     && subscriberMethod.equals(otherSubscription.subscriberMethod);  
  25.         } else {  
  26.             return false;  
  27.         }  
  28.     }  
  29.   
  30.     @Override  
  31.     public int hashCode() {  
  32.         return subscriber.hashCode() + subscriberMethod.methodString.hashCode();  
  33.     }  
  34. }  

其实就是很简单的一个对象,我们可以看做一个简单的java bean就好了,他的功能就是封装了一个订阅者实体对象(  final Object subscriber;)和上面我们解释过的,一个Mehtod信息的封装类( final SubscriberMethod subscriberMethod;)。

继续回到主线,我们可以看到,会把EventType和Subscriptions关联起来,很好理解,可以想象的到,我们Post一个事件的时候,一般会带一个事件类型,也就是post方法中的参数。
而一个EventType可能对应很多个方法和对象,然后就把他们存储起来了,源代码体现如下:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Subscription newSubscription = new Subscription(subscriber, subscriberMethod);  
  2.        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);  
  3.        if (subscriptions == null) {  
  4.            subscriptions = new CopyOnWriteArrayList<>();  
  5.            subscriptionsByEventType.put(eventType, subscriptions);  
  6.        } else {  
  7.            if (subscriptions.contains(newSubscription)) {  
  8.                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "+ eventType);  
  9.            }  
  10.        }  
然后把一个个的新new出来的 Subscription添加了 subscriptions中,而subscriptions又和evetType关联起来了。添加新new出来的Subscription的时候,它会根据事件方法当时声明的时候,设置的priority注解信息,当priority的放在List的队列前面。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int size = subscriptions.size();  
  2.        for (int i = 0; i <= size; i++) {  
  3.            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {  
  4.                subscriptions.add(i, newSubscription);  
  5.                break;  
  6.            }  
  7.        }  

再往下走,就是用实体对象和EventType关联了,这个也不难理解,我们可以理解为,一个实体对象可以写很多个订阅方法,但是没一个订阅方法可能会是不同的EventType(订阅方法的参数类型),所以最后把 eventType添加到了 subscribedEvents之中。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);  
  2.        if (subscribedEvents == null) {  
  3.            subscribedEvents = new ArrayList<>();  
  4.            typesBySubscriber.put(subscriber, subscribedEvents);  
  5.        }  
  6.        subscribedEvents.add(eventType);  
最后一部分的代码是处理Sticky事件的逻辑,我们知道EventBus是可以调用成员方法
来postSticky(Object event)方法来提交一个事件。 主要判断 subscriberMethod的sticky是否为true ,如果是,就从 stickyEvents集合中 获取所有相同事件类型的且设置了sticky属性的订阅者和订阅方法,然后就调用 checkPostStickyEventToSubscription(newSubscription, stickyEvent);方法 将事件发送出去了。

OK,到这里基本上register模块都解释的差不多了,上面我们也看到,各种事件对象、方法对象、和订阅者对象都已经封存起来,可以等待post事件的时候,将事件发送出去。
3. post(Object event) 发布订阅事件

Ok我们继续往下分析关于事件post的时候的实现原理。
我们知道我们在拿到EventBus的实例单例对象的时候,可以简单的就调用的他的post刚发,将一个特定的订阅事件类型发送出去,订阅者的订阅方法就能被回调了,我们来直接看这个方法吧。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** Posts the given event to the event bus. */  
  2.    public void post(Object event) {  
  3.        PostingThreadState postingState = currentPostingThreadState.get();  
  4.        List<Object> eventQueue = postingState.eventQueue;  
  5.        eventQueue.add(event);  
  6.   
  7.        if (!postingState.isPosting) {  
  8.            postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();  
  9.            postingState.isPosting = true;  
  10.            if (postingState.canceled) {  
  11.                throw new EventBusException("Internal error. Abort state was not reset");  
  12.            }  
  13.            try {  
  14.                while (!eventQueue.isEmpty()) {  
  15.                    postSingleEvent(eventQueue.remove(0), postingState);  
  16.                }  
  17.            } finally {  
  18.                postingState.isPosting = false;  
  19.                postingState.isMainThread = false;  
  20.            }  
  21.        }  
  22.    }  

首先从 currentPostingThreadState( LocalThread)中获取一个与当前线程关联的 PostingThreadState对象,这个对象很简单,其实就是一个记录一个线程事件post状态的实体,可以稍微看看他的代码。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** For ThreadLocal, much faster to set (and get multiple values). */  
  2.    final static class PostingThreadState {  
  3.        final List<Object> eventQueue = new ArrayList<Object>();  
  4.        boolean isPosting;  
  5.        boolean isMainThread;  
  6.        Subscription subscription;  
  7.        Object event;  
  8.        boolean canceled;  
  9.    }  

没错就是这么简单,其成员也很好理解,eventQueue 很明显就是一个事件队列,isPosting 这个boolean类型的标记只要就是记录当先线程的事件发布状态,isMainThread主要就是标记当前线程是否为主线程,event事件类型、canceled是否取消post。

首先判断状态,假如下载正在post事件的时候,就不在接受post其他事件了,我们直接分析if语句块里面的代码吧,如果事件队列为空的话,就结束post过程,方法执行结束。
否则进入 postSingleEvent(eventQueue.remove(0), postingState);方法中,然后每次都是获取事件队列中的栈顶的一个事件,注意是使用的remove(0)的方式来获取,直接来看postSingleEvent(Object event, PostingThreadState postingState)方法吧。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {  
  2.         Class<?> eventClass = event.getClass();  
  3.         boolean subscriptionFound = false;  
  4.         if (eventInheritance) {  
  5.             List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);  
  6.             int countTypes = eventTypes.size();  
  7.             for (int h = 0; h < countTypes; h++) {  
  8.                 Class<?> clazz = eventTypes.get(h);  
  9.              subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);  
  10.             }  
  11.         } else {  
  12.             subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);  
  13.         }  
  14.         if (!subscriptionFound) {  
  15.             if (logNoSubscriberMessages) {  
  16.                 Log.d(TAG, "No subscribers registered for event " + eventClass);  
  17.             }  
  18.             if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&  
  19.                     eventClass != SubscriberExceptionEvent.class) {  
  20.                 post(new NoSubscriberEvent(this, event));  
  21.             }  
  22.         }  
  23.     }  

首先我们知道 eventInheritance的值是为true的,所以会先调用llookupAllEventTypes(eventClass)获取eventClass所有父类的后者接口类型的class对象,存到eventTypes 集合中,这里就不贴出lookupAllEventTypes(eventClass)的代码实现了,因为他的代码很简单,主要就是想上获取父类或者接口类型的class对象,因为比如父类或者接口为Car,BMW extends Car,这些都会被获取出来,记住是eventClass的父类和接口的calss对象哦,然后挨个遍历evnetClass对象。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. for (int h = 0; h < countTypes; h++) {  
  2.                 Class<?> clazz = eventTypes.get(h);  
  3.              subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);  
  4. }  

然后调用了 postSingleEventForEventType(event, postingState, clazz);方法,我们直接看这个方法。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {  
  2.         CopyOnWriteArrayList<Subscription> subscriptions;  
  3.         synchronized (this) {  
  4.             subscriptions = subscriptionsByEventType.get(eventClass);  
  5.         }  
  6.         if (subscriptions != null && !subscriptions.isEmpty()) {  
  7.             for (Subscription subscription : subscriptions) {  
  8.                 postingState.event = event;  
  9.                 postingState.subscription = subscription;  
  10.                 boolean aborted = false;  
  11.                 try {  
  12.                     postToSubscription(subscription, event, postingState.isMainThread);  
  13.                     aborted = postingState.canceled;  
  14.                 } finally {  
  15.                     postingState.event = null;  
  16.                     postingState.subscription = null;  
  17.                     postingState.canceled = false;  
  18.                 }  
  19.                 if (aborted) {  
  20.                     break;  
  21.                 }  
  22.             }  
  23.             return true;  
  24.         }  
  25.         return false;  
  26.     }  
OK,我们看到,从subscriptionsByEventType中取出一个subscriptions 对象,我们应该还有印象,前面我们讲过,说事件类型和事件订阅者关联起来了,一个订阅者可以实现多个订阅方法,接收不同事件类型,所以事件类型和订阅者关联起来, 将所有订阅者保存成集合,和事件类型关联了,Ok遍历subscriptions  ,然后调用postToSubscription(subscription, event, postingState.isMainThread);方法去post事件给订阅者。我们直接看这个方法。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {  
  2.        switch (subscription.subscriberMethod.threadMode) {  
  3.            case POSTING:  
  4.                invokeSubscriber(subscription, event);  
  5.                break;  
  6.            case MAIN:  
  7.                if (isMainThread) {  
  8.                    invokeSubscriber(subscription, event);  
  9.                } else {  
  10.                    mainThreadPoster.enqueue(subscription, event);  
  11.                }  
  12.                break;  
  13.            case BACKGROUND:  
  14.                if (isMainThread) {  
  15.                    backgroundPoster.enqueue(subscription, event);  
  16.                } else {  
  17.                    invokeSubscriber(subscription, event);  
  18.                }  
  19.                break;  
  20.            case ASYNC:  
  21.                asyncPoster.enqueue(subscription, event);  
  22.                break;  
  23.            default:  
  24.                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);  
  25.        }  
  26.    }  

所以上面的代码已经很明显了,就是根据ThreadMode来在不同的线程中发布事件,第一种   case POSTING: 是默认方式下的,表示在当前线程中执行,也就是在事件post所在线程中执行,我们看到它是直接调用  invokeSubscriber(subscription, event)方法去执行了,看看这个方法吧。
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void invokeSubscriber(Subscription subscription, Object event) {  
  2.        try {  
  3.    subscription.subscriberMethod.method.invoke(subscription.subscriber, event);  
  4.        } catch (InvocationTargetException e) {  
  5.            handleSubscriberException(subscription, event, e.getCause());  
  6.        } catch (IllegalAccessException e) {  
  7.            throw new IllegalStateException("Unexpected exception", e);  
  8.        }  
  9.    }  

我们看到,代码很简单,就一句话,利用发射的方式去执行了,其他的都是异常捕获。

接着看第二种    case MAIN:很明显是在主线程中执行的 我们看这个case下的实现方式。
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if (isMainThread) {  
  2.                     invokeSubscriber(subscription, event);  
  3.                 } else {  
  4.                     mainThreadPoster.enqueue(subscription, event);  
  5.   }  

很好理解,如果当前已经是在主线程中,就直接跟第一种方式一样,直接在当前线程中执行就OK了,如果当前不是主线程,那么只能通过主线程的Handler来发送handler事件消息到主线程去执行了,使用mainThreadPoster将事件加入执行队列,mainThreadPoster我们在一开始的时候我们讲过,他们的实现也很简单,这个具体怎么发送和执行可以去看看,但是他们最后都是调用EventBus的invokeSubscriber(subscription, event);方法来执行的。

第三种 case BACKGROUND: 很明显,就是在后台子线程中执行了,看看这个case下的代码实现吧。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if (isMainThread) {  
  2.                backgroundPoster.enqueue(subscription, event);  
  3.            } else {  
  4.                invokeSubscriber(subscription, event);  
  5.     }  
也很简单,直接判断当前是否为主线程,如果主线程的话,就直接使用 backgroundPoster来将事件加入执行队列, 
backgroundPoster我们在前面做过铺垫,他就是一个Runnable的实现体,接着调用了它自己的enqueue方法,我们稍微提一下这方法。
 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void enqueue(Subscription subscription, Object event) {  
  2.        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);  
  3.        synchronized (this) {  
  4.            queue.enqueue(pendingPost);  
  5.            if (!executorRunning) {  
  6.                executorRunning = true;  
  7.                eventBus.getExecutorService().execute(this);  
  8.            }  
  9.        }  
  10.    }  

最后线程执行,就调用了  
backgroundPoster的run方法。
 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2.    public void run() {  
  3.        try {  
  4.            try {  
  5.                while (true) {  
  6.                    PendingPost pendingPost = queue.poll(1000);  
  7.                    if (pendingPost == null) {  
  8.                        synchronized (this) {  
  9.                            // Check again, this time in synchronized  
  10.                            pendingPost = queue.poll();  
  11.                            if (pendingPost == null) {  
  12.                                executorRunning = false;  
  13.                                return;  
  14.                            }  
  15.                        }  
  16.                    }  
  17.                    eventBus.invokeSubscriber(pendingPost);  
  18.                }  
  19.            } catch (InterruptedException e) {  
  20.                Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);  
  21.            }  
  22.        } finally {  
  23.            executorRunning = false;  
  24.        }  
  25.    }  

他最后是通过queue.poll(1000);取出一个事件,将事件交个了EventBus中线程池来执行,从而达到了 
backgroundPost的效果,也就是子线程执行的效果。


但是我们这里应该需要注意一个地方,那就是
 
queue.enqueue(pendingPost);这个将事件的入队操作,这里还是有必要看一下 queue这个队列是个什么样的实现方式。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. final class BackgroundPoster implements Runnable {  
  2.   
  3.     private final PendingPostQueue queue;  
  4.     private final EventBus eventBus;  
  5.   
  6.     private volatile boolean executorRunning;  
  7.   
  8.     BackgroundPoster(EventBus eventBus) {  
  9.         this.eventBus = eventBus;  
  10.         queue = new PendingPostQueue();  
  11.     }  
  12.   
  13.     public void enqueue(Subscription subscription, Object event) {  
  14.         PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);  
  15.         synchronized (this) {  
  16.             queue.enqueue(pendingPost);  
  17.             if (!executorRunning) {  
  18.                 executorRunning = true;  
  19.                 eventBus.getExecutorService().execute(this);  
  20.             }  
  21.         }  
  22.     }  

我们看到 queue 是一个PendingPostQueue类型的实体成员变量。我们直接贴上这个类的代码来看看。
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)  
  2.   
  3. package org.greenrobot.eventbus;  
  4.   
  5. final class PendingPostQueue {  
  6.     private PendingPost head;  
  7.     private PendingPost tail;  
  8.   
  9.     synchronized void enqueue(PendingPost pendingPost) {  
  10.         if (pendingPost == null) {  
  11.             throw new NullPointerException("null cannot be enqueued");  
  12.         }  
  13.         if (tail != null) {  
  14.             tail.next = pendingPost;  
  15.             tail = pendingPost;  
  16.         } else if (head == null) {  
  17.             head = tail = pendingPost;  
  18.         } else {  
  19.             throw new IllegalStateException("Head present, but no tail");  
  20.         }  
  21.         notifyAll();  
  22.     }  
  23.   
  24.     synchronized PendingPost poll() {  
  25.         PendingPost pendingPost = head;  
  26.         if (head != null) {  
  27.             head = head.next;  
  28.             if (head == null) {  
  29.                 tail = null;  
  30.             }  
  31.         }  
  32.         return pendingPost;  
  33.     }  
  34.   
  35.     synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {  
  36.         if (head == null) {  
  37.             wait(maxMillisToWait);  
  38.         }  
  39.         return poll();  
  40.     }  
  41.   
  42. }  
从上面的代码我们可以看出,poll和enqueue 都加上 synchronized ,他就是模拟了一个事件队列,enqueue就是将事件入队的动作,当然还模拟了一个事件的队列的队头队尾和next,首先上面代码一开始head为和tail应该都为null,所以会执行如下代码。
             head = tail = pendingPost;
将当前队列的头尾都设置为 pendingPost(当前事件),然后调用notifyAll()方法,通知线程去执行任务,就是把任务交给EventBus中声明的线程池来执行,最后调用到了run方法了,在run方法中调用了 queue.poll(1000);来一个事件,看看poll(int maxMillisToWait)方法吧。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {  
  2.        if (head == null) {  
  3.            wait(maxMillisToWait);  
  4.        }  
  5.        return poll();  
  6.    }  
也是很简单啊,直接判断队头是否为空,如果为空就让线程先等1000毫秒,所以最后只有在enqueue被调用,加入新的事件后,notifyAll唤醒线程去调用无参数的重载方法来取出事件返回出去。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. synchronized PendingPost poll() {  
  2.         PendingPost pendingPost = head;  
  3.         if (head != null) {  
  4.             head = head.next;  
  5.             if (head == null) {  
  6.                 tail = null;  
  7.             }  
  8.         }  
  9.         return pendingPost;  
  10.     }  
方法也很简单,首先直接把head赋值给一个新的 pendingPost变量,再判断如果head不为空,直接把下一个next事件复制给head,典型的先进先出队列,然后返回pendingPost。

其实到这里其实也有两个很重要的知识点,队列概念的巧妙是使用,先进先出方式的使用,还有一个是生产者和消费者的概念。
回归主线,判断如果不是主线程,就刚好,直接执行事件就可以了,看最后一种
case ASYNC:
这种其实跟 BACKGROUND一样的执行方式,因为asyncPoster本身也是一个Runnable的实现体,最后也调用了enqueue方法把任务交给了EventBus中的线程池来执行,具体代码基本和BACKGROUND的分析一样的。但是这个和BACKGROUND是有区别的,它是任何时候都要在子线程中执行的.


转载自:http://blog.csdn.net/hua631150873/article/details/51377131




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值