EventBus注意点

研究了EventBus源码,不贴分析过程,有兴趣的同学自己查看阅读,这才是真程序员(PS:真不是我不擅长写文档,真的呦)。

源码地址:https://github.com/greenrobot/EventBus

官方文档地址:http://greenrobot.org/eventbus/


1. EventBus有几种ThreadMode:

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


POSTING:默认模式,表示在当前线程执行
MAIN:在主线程中执行,如果post事件发生是主线程,则直接调用,如果不是,在使用handler进行处理
BACKGROUND:在线程池中执行
ASYNC:在线程池中执行


BackgroundThreadAsync的区别:

a. BackgroundThread会判断是否是主线程,是主线程会调用线程池来解决,不是主线程则直接在BackgroundThread当前线程中调用;而Async都会在线程池中调用。
b. BackgroundThread的任务会在线程池中顺序执行(一次只能执行一个),而Async在没有限制。

下面看看backgroundPoster与asyncPoster的源码就知道了:

background:

    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) {
                    //如果queue中没有数据,则等待1s中之后再取。因为线程执行是无须的
                    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;
        }
    }


async:

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

2. 线程池使用的是什么线程池?

答:newCachedThreadPool,自己体会

3. 各个ThreadMode都会使用PendingPostQuene存取PendingPost,如何保证之间不会去错?
答:HandlerPoster(Main),BackgroundPoster(background),AsyncPoster(async)各生成一个PendingPostQuene。


4. EventBus工作原理?

答:当register时,根据注解把相关方法(一个参数,public,非static,非abstract)放到map中(当前类与所有方法参数的map、方法参数与所有方法的map);

当unregister时,还是贴代码吧,手写容易产生误解:

 /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
    private void unsubscribeByEventType(Object subscriber, Class eventType) {
        //得到当前参数的所有方法(subscriptionsByEventType:方法参数与所有方法的map)
        List subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                //subscription中有两个对象,一个是当前类对象:subscriber;另一个是注册的方法对象
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

    /** Unregisters the given subscriber from all event classes. */
    public synchronized void unregister(Object subscriber) {
        //得到当前类的所有方法参数(typesBySubscriber:当前类与所有方法参数的map)
        List> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class eventType : subscribedTypes) {
                //把方法参数从“方法参数与所有方法的map”中删除,见上面方法
                unsubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else {
            Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

当post时,根据参数类型,得到所有的方法,通过反射调用。


5. sticky是什么gui?

答:当给方法A用sticky注解时,会立即根据A的方法参数去查找stickyEvents(一个map,参数class为key,参数为value,在postSticky是放入数据)里面的数据,找到了就直接调用A方法,可通过removeStickyEvent需要移除map里的数据,根据需要使用。


6. 其他的各种配置什么含义?

答:偷个图(一般使用默认的就可以)

EventBus注意点_第1张图片



7. 怎么使用?

答:就不告诉你




你可能感兴趣的:(内部原理及源码)