EventBus源码解析(二)

上一篇我们介绍了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 的源码分析到这里就结束了,我们的问题都已经解决了,但是里面还有很多的细节,这里我就不深纠了,想了解的,大家可以自己去看看源码。

你可能感兴趣的:(EventBus源码解析(二))