上一篇我们介绍了EventBus回调的主要流程,解决问题一,今天我们来解决问题二
问题二
怎么根据ThreadMode来切换线程
继续上一篇内容
前面我们讲实现流程的时候发现只有在postToSubscription()方法中用到了threadMode,那么有关线程的钱换肯定就是在这个方法中,下面来看方法的实现
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
//在Subscribe 注解中赋不同的threadMode 就会调用不同的方法
switch (subscription.subscriberMethod.threadMode) {
//默认的threadMode,直接执行方法
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
//判断post方法是否在煮线程中
if (isMainThread) {
//如果在,直接执行方法
invokeSubscriber(subscription, event);
} else {
//不在
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.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);
}
}
来看mainThreadPoster 的初始化
EventBus(EventBusBuilder builder) {
....
mainThreadSupport = builder.getMainThreadSupport();
//初始化,其实就是调用mainThreadSupport.createPoster(this)方法
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
.......
}
MainThreadSupport getMainThreadSupport() {
if (mainThreadSupport != null) {
return mainThreadSupport;
} else if (Logger.AndroidLogger.isAndroidLogAvailable()) {
Object looperOrNull = getAndroidMainLooperOrNull();
//返回一个带主线程Looper的MainThreadSupport对象
return looperOrNull == null ? null :
new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
} else {
return null;
}
}
//获取主线程的Looper
Object getAndroidMainLooperOrNull() {
try {
return Looper.getMainLooper();
} catch (RuntimeException e) {
// Not really a functional Android (e.g. "Stub!" maven dependencies)
return null;
}
}
来看AndroidHandlerMainThreadSupport的实现
public interface MainThreadSupport {
boolean isMainThread();
Poster createPoster(EventBus eventBus);
class AndroidHandlerMainThreadSupport implements MainThreadSupport {
private final Looper looper;
public AndroidHandlerMainThreadSupport(Looper looper) {
this.looper = looper;
}
@Override
public boolean isMainThread() {
return looper == Looper.myLooper();
}
@Override
public Poster createPoster(EventBus eventBus) {
return new HandlerPoster(eventBus, looper, 10);
}
}
}
很简单,所以mainThreadPoster其实就是一个HandlerPoster(eventBus, looper, 10)对象,其中这个looper就是主线程的looper,所以mainThreadPoster.enqueue()方法就是调用HandlerPoster对象中的enqueue()方法,其实看到了Looper.getMainLooper()这个就应该知道是使用了handler来切回主线程。
继续看HandlerPoster 的实现
//和我们前面猜想的一样,继承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) {
//调用构造函数,将主线程的looper传进去
super(looper);
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) {
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;
}
}
}
跟我们猜想的一样,继承Handler 将主线程的looper传进去,实现子线程到主线程的切换
其他的threadMode 原理都和这个差不多,创建不同的Poster 分别执行,在这里我就不一一分析了,大家看一下源码应该能很清楚的理解
结语
eventBust 的源码分析到这里就结束了,我们的问题都已经解决了,但是里面还有很多的细节,这里我就不深纠了,想了解的,大家可以自己去看看源码。