EventBus源码阅读(二)——Poster

  上一节在阅读了EventBus的消息发送后,停在了postToSubscription方法上:

    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.enqueue(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);
        }
    }

   在不同的模式下,当前方法在不同线程中调用,会使用不同的Poster。上次对这一点没有深究,今天来粗略的看一看。

  从上面的代码中,我们可以看到,除了直接执行方法 invokeSubscriber(subscription, event);外,还有几个特殊的Poster,分别是mainThreadPoster,backgroundPoster,和asyncPoster。

  我们来一一阅读。

  mainThreadPoster的类叫作HandlerPoster,代码不长,总共80来行。

  

final class HandlerPoster extends Handler {

    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

    HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }

    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;
        }
    }
}

  可以看到HandlerPoster继承了Handler。方法enqueue主要做了两件事。

  一、将事件请求放入请求队列queue中。

  二、发送一个message到MainLooper中。

  每当HandlerPoster发送message,其中的handleMessage就要开始工作。EventBus为其设置了最大工作时间。在工作时间内,程序会不断地从queue中poll出请求,在主线程中执行它,直到queue队列为空,或是到达最大工作时间,才会结束。我们可以看到,HandlerPoster其实就是对消息的发送做了处理,通过Handler,将其置于MainThread中来执行。

  BackgroundPoster:

  BackgroundPoster则是实现了Runnable接口。

final class BackgroundPoster implements Runnable {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    private volatile boolean executorRunning;

    BackgroundPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);
            }
        }
    }

    @Override
    public void run() {
        try {
            try {
                while (true) {
                    PendingPost pendingPost = queue.poll(1000);
                    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) {
                Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

}

  BackgroundPoster也维护了一个请求队列。与HandlerPoster不同的是,它不再使用message来发动任务的执行。而是eventBus.getExecutorService().execute(this);这个方法最终可以追溯到EventBusBuilder中的DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();也就是说,在BackgroundPoster中执行的任务一定不在主线程。另一个与HandlerPoster不同的点是,BackgroundPoster没有最大工作时间,但它有个最大等待时间——1000ms。如果队列为空,在等待1000ms后,队列中依然没有新的事件加入,再表示事件请求已全部执行。

AsyncPoster:

  AsyncPoster的实现最为简单,它的功能是,不能当前处于什么线程,一定都会新开一个线程来执行这个任务。

  

class AsyncPoster implements Runnable {

    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);
    }

}

   代码比较简单,我们可以看出AsyncPoster是在BackgroundPoster上做的减法。去掉了线程保护(因为新开),去掉了wait(也是因为新开)。

  通过以上阅读,我们大致对EventBus的事件发送机制有了了解。下一节,我们将开始阅读,它的订阅机制。

Done~

原文地址:https://www.cnblogs.com/fishbone-lsy/p/5410699.html