EventBus源码分析

EventBus的使用这里就不讲了,从几个问题来分析源码吧

1:subscribe 注解的方法如何读取,并维护数据

2:post后如何找到对应的方法

3:线程间如何切换

先举个栗子

public class Test1 {
    private final String TAG = getClass().getSimpleName();
    public Test1() {
        EventBus.getDefault().register(this);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void test1Fun(TestEvent event) {
        Log.e(TAG," --- test1Fun ---- event=" + event);
    }

    @Subscribe(threadMode = ThreadMode.ASYNC) 
    public void test2Fun(TestEvent2 event) { 
      Log.e(TAG," --- test1Fun ---- event=" + event); 
    }

    public void destroy() {
        EventBus.getDefault().unregister(this);
    }
}

这个是大家常用的写法。后面就直接以这个栗子来说明了。


一:subscribe 注解的方法如何读取,并维护数据

   EventBus里面有2个变量:

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;

  该变量存储了某个参数对应的所有的注解方法

key:方法的类型   TestEvent.class,value: 所有方法类型的集合

List<> {

           Subscription(test1, new SubscriberMethod(test1Fun.Method, ThreadMode.MAIN, TestEvent.class,xx)),

}

key:方法的类型   TestEvent2.class,value: 所有方法类型的集合

List<> {

           Subscription(test1, new SubscriberMethod(test2Fun.Method, ThreadMode.MAIN, TestEvent2.class,xx)),

}

也就是说监听TestEvent消息的方法类型(test1Fun)都存在了subscriptionsByEventType中了。后续post消息时,会从subscriptionsByEventType中查找方法类型。

final class Subscription {
    final Object subscriber;//调用regiest的类的引用,如test1
    final SubscriberMethod subscriberMethod;
}
public class SubscriberMethod {
    final Method method;    //被注解的方法 如上面的Test1Fun
    final ThreadMode threadMode;    //线程模型
    final Class<?> eventType;   //参数类型,如上面的TestEvent
    final int priority;
    final boolean sticky;
    /**
     * Used for efficient comparison
     */
    String methodString;
}
private final Map<Object, List<Class<?>>> typesBySubscriber;
//存储了某个类下面的所有注释的参数<test1,List<Parmas.class>>

  key:调用regiest的类 test1,value:所有方法类型的集合

List<>{

    TestEvent.class,

    TestEvent2.class

}

typesBySubscriber是用来检测类是否被regeist过,或在unregiest时清理该类下面所有的方法。


2:post后如何找到对应的方法

    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);

        if (!postingState.isPosting) {
            postingState.isMainThread = isMainThread();
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }
    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        ...........................................
        if (eventInheritance) {
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);//找到该event类的所有父类和接口
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class<?> clazz = eventTypes.get(h);
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }
        ..........................................
    }

通过lookupAllEventTypes找到event所有的父类和接口,也就是说发送的消息也会发送给他的父类和接口,

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                ........................
    }

从subscriptionsByEventType中取出了eventClass所对应的方法,然后一个一个的往该方法中丢数据。这里就能看出他是怎么知道对应的post方法。


3:线程间如何切换

    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 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);
        }
    }
postToSubscription判断运行的线程,然后对不同的线程做对POST来说直接调用invokeSubscriber
    void invokeSubscriber(Subscription subscription, Object event) {
        try {
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }

我们能看到是通过反射的方法去调用的。

而主线的处理则是在mainThreadPoster里面处理的。

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) {
        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) {
            .................................
        }
    }

    @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;
                        }
                    }
                }
                ........................
            }
        } finally {
            handlerActive = rescheduled;
        }
    }
}
HandlerPoster其实是运行在主线程的handler,所以在handleMessage中运行的方法都是在主线程中执行的。

后台线程backgroundPoster。就是一个运行在线程池中的Runnable。

final class BackgroundPoster implements Runnable, Poster {
    ...................
    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);
            .............................
    }

}
asyncPoster和backgroundPoster一样,也是一个runnable 不同的是backgroundPoster的线程可以复用,当 executorRunning=true的时候就不会开启新的线程。而asyncPoster每次都会开启新线程。
class AsyncPoster implements Runnable, Poster {

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

}

至此3个问题已经讲解完毕

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值