Android EventBus源码解析

一、EventBus的简单使用流程

Android EventBus的简单使用》中介绍了EventBus的简单使用,从

    EventBus.getDefault().register(this);

开始,注意在类中实现相应的onEvent方法:  

    public void onEventMainThread(ActivityToServiceEvent event) {
        String msg = event.getMsg();
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

onEventMainThread表示响应在MainThread线程中进行;
    发送消息采用:
    EventBus.getDefault().post(new ServiceToActivityEvent("MyEvent Send!"));
    解除绑定使用:
    EventBus.getDefault().unregister(this);

二、源码分析:

    从源码中来看上述消息传递是如何实现的,首先类需要register EventBus,在注册之前可以看到使用的getDefault(),估计是个单件模式。

(一)注册过程:

1、EventBus#getDefault:

static volatile EventBus defaultInstance;

// 可以看到是多线程环境下简单的Singleton模式
/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                // 调用构造函数
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}
    简单的Singleton模式,其主要初始化工作都在构造函数中进行; 


2、EventBus#EventBus:

private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
public EventBus() {
    this(DEFAULT_BUILDER);
}

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final HandlerPoster mainThreadPoster;
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
private final SubscriberMethodFinder subscriberMethodFinder;
private final ExecutorService executorService;

private final boolean throwSubscriberException;
private final boolean logSubscriberExceptions;
private final boolean logNoSubscriberMessages;
private final boolean sendSubscriberExceptionEvent;
private final boolean sendNoSubscriberEvent;
private final boolean eventInheritance;

EventBus(EventBusBuilder builder) {
    subscriptionsByEventType = new HashMap<Class<?>, CopyOnWriteArrayList<Subscription>>();
    typesBySubscriber = new HashMap<Object, List<Class<?>>>();
    stickyEvents = new ConcurrentHashMap<Class<?>, Object>();
    mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
    backgroundPoster = new BackgroundPoster(this);
    asyncPoster = new AsyncPoster(this);
    subscriberMethodFinder = new SubscriberMethodFinder(builder.skipMethodVerificationForClasses);
    logSubscriberExceptions = builder.logSubscriberExceptions;
    logNoSubscriberMessages = builder.logNoSubscriberMessages;
    sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
    sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
    throwSubscriberException = builder.throwSubscriberException;
    eventInheritance = builder.eventInheritance;
    executorService = builder.executorService;
}
    可以看到根据EventBusBuilder进行一些变量的初始化,上述变量在具体用到时再介绍相应的具体含义。

    EventBus实例创建之后,接着来看注册过程。


3、EventBus#register:

public void register(Object subscriber) {
    register(subscriber, false, 0);
}
public void register(Object subscriber, int priority) {
    register(subscriber, false, priority);
}
public void registerSticky(Object subscriber) {
    register(subscriber, true, 0);
}
public void registerSticky(Object subscriber, int priority) {
    register(subscriber, true, priority);
}

// 最终使用的注册函数
/* @params: subscriber即表示注册EventBus的类对象
*           sticky表示消息是否立即发送
*           priority表示优先级,优先级越高则会被有限调用*/
private synchronized void register(Object subscriber, boolean sticky, int priority) {
    // 这里看到的Method,是通过反射来查找注册类subscriber中的所有相关onEvent函数的
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
    // 对于找到每一个onEvent函数进行响应
    for (SubscriberMethod subscriberMethod : subscriberMethods) {
        subscribe(subscriber, subscriberMethod, sticky, priority);
    }
}

     前面提供了一系列重载的register函数可供使用,最终调用的都是最后面的同步函数,可以看到在同步函数中,有个List类型的subscriberMethods变量,其工作机制是通过反射查找注册类subscriber中所有相关的onEvent函数,添加到List中,然后再遍历Methods,调用subscribe来响应每一个函数。这也解释了在使用EventBus问什么要定义上述一系列onEvent函数。


4、SubscriberMethodFinder#findSubscriberMethods:

private static final Map<String, List<SubscriberMethod>> methodCache = new HashMap<String, List<SubscriberMethod>>();

// 传入的参数为注册类的Class对象,SubscriberMethod类是对onEvent方法的封装
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    String key = subscriberClass.getName();
    List<SubscriberMethod> subscriberMethods;

    // 由前面可以看到methodCache是一个HashMap,存储的是注册类名与类中定义的onEvent方法List
    synchronized (methodCache) {
        subscriberMethods = methodCache.get(key);
    }
    // 如果已经注册过,则methodCache已经保存了该注册类中的Methods,直接返回;
    if (subscriberMethods != null) {
        return subscriberMethods;
    }
    subscriberMethods = new ArrayList<SubscriberMethod>();
    Class<?> clazz = subscriberClass;
    HashSet<String> eventTypesFound = new HashSet<String>();
    StringBuilder methodKeyBuilder = new StringBuilder();
    while (clazz != null) {
        String name = clazz.getName();
        if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
            // Skip system classes, this just degrades performance
            break;
        }

        // 通过反射机制,获得类中所有方法Methods
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            String methodName = method.getName();
            // @value ON_EVENT_METHOD_NAME = "onEvent";
            // 可以看到这里面的就是遍历所有方法,然后判断是都是以onEvent开头,即代码中注册的一系列的onEvent方法
            if (methodName.startsWith(ON_EVENT_METHOD_NAME)) {
                int modifiers = method.getModifiers();

                // 这里判断方法是public类型,且不是static和abstract
                if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    // 继续限定方法的参数只能为1个
                    if (parameterTypes.length == 1) {
                        String modifierString = methodName.substring(ON_EVENT_METHOD_NAME.length());
                        ThreadMode threadMode;

                        // 在根据方法名区别出post,mainThread等四种定义的onEvent方法
                        if (modifierString.length() == 0) {
                            threadMode = ThreadMode.PostThread;
                        } else if (modifierString.equals("MainThread")) {
                            threadMode = ThreadMode.MainThread;
                        } else if (modifierString.equals("BackgroundThread")) {
                            threadMode = ThreadMode.BackgroundThread;
                        } else if (modifierString.equals("Async")) {
                            threadMode = ThreadMode.Async;
                        } else {
                            if (skipMethodVerificationForClasses.containsKey(clazz)) {
                                continue;
                            } else {
                                throw new EventBusException("Illegal onEvent method, check for typos: " + method);
                            }
                        }
                        Class<?> eventType = parameterTypes[0];
                        methodKeyBuilder.setLength(0);
                        methodKeyBuilder.append(methodName);
                        methodKeyBuilder.append('>').append(eventType.getName());
                        String methodKey = methodKeyBuilder.toString();
                        if (eventTypesFound.add(methodKey)) {
                            // 将检索到的方法组装成SubscriberMethod,添加到List中
                            subscriberMethods.add(new SubscriberMethod(method, threadMode, eventType));
                        }
                    }
                } else if (!skipMethodVerificationForClasses.containsKey(clazz)) {
                    Log.d(EventBus.TAG, "Skipping method (not public, static or abstract): " + clazz + "."
                            + methodName);
                }
            }
        }
        // 注意最后一步,可以看到这里不仅扫描当前类,同时还会对其父类进行扫描,查找所有的onEvent方法
        clazz = clazz.getSuperclass();
    }
    if (subscriberMethods.isEmpty()) {
        throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called "
                + ON_EVENT_METHOD_NAME);
    } else {
        synchronized (methodCache) {
            methodCache.put(key, subscriberMethods);
        }
        return subscriberMethods;
    }
}
    可以看到上面的查找逻辑十分简单,通过反射机制,获取注册类中的所有Methods,然后根据Methods名称,删选出以onEvent开头的,修饰符为public,并且不为static和abstaract的方法,然后再根据名称区分出postThread、mainThread等四种方法类型,统一添加到List中,SubscriberMethod中包含的信息有method对象,方法对应的threadMode(如postThread等),还有onEvent方法中的Event参数类型class;

    这里注意代码中最后一步,不仅对当前类进行扫描,同时还会扫描其父类,将所有扫描到的Methods添加进去。

    最后EventBus还会使用HashMap(methodCache),将当前类名与扫描到的Methods保存起来,使得重复注册时可以避免扫描直接返回。

    接下来,继续回到register中,对每一个method调用subscribe方法。


5、EventBus#subscribe:

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
    Class<?> eventType = subscriberMethod.eventType;

    // subscriptionsByEventType是一个HashMap,用来存储eventType对应的方法
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
    // 如果对应subscriptions不存在,则创建
    if (subscriptions == null) {
        subscriptions = new CopyOnWriteArrayList<Subscription>();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                    + eventType);
        }
    }

    // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
    // subscriberMethod.method.setAccessible(true);
    // Subscriptions的添加
    int size = subscriptions.size();
    for (int i = 0; i <= size; i++) {
        // 可以看到是根据priority优先级的顺序进行插入的
        if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }

    // 存储subscriber,存储主要用于判断该class是否已经创建
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<Class<?>>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    subscribedEvents.add(eventType);

    // 可以看到前面register参数传递中的sticky参数,如果其为true,则直接发送stickyEvent(如果存在的话)
    if (sticky) {
        Object stickyEvent;
        synchronized (stickyEvents) {
            stickyEvent = stickyEvents.get(eventType);
        }
        if (stickyEvent != null) {
            // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
            // --> Strange corner case, which we don't take care of here.
            postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
        }
    }
}
    subscribe的作用主要是将上面通过反射扫描到的所有onEvent methods添加到EventBus的变量subscriptionsByEventType中来,可以看到同一种eventType(事件类型)的处理函数会被放到一起;将注册类按照priority顺序添加到变量subscriptions中,用以记录哪些类已经注册,哪些类未注册。

    至此,register操作已经完成;

    下面来分析消息传递过程,即从post开始;


(二)消息传递过程:

1、EventBus#post:

// 可以看到currentPostingThreadState使用ThreadLocal机制
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
    @Override
    protected PostingThreadState initialValue() {
        return new PostingThreadState();
    }
};
/** Posts the given event to the event bus. */
public void post(Object event) {
    // 获取当前线程的PostingThreadState
    PostingThreadState postingState = currentPostingThreadState.get();
    // eventQueue事件队列
    List<Object> eventQueue = postingState.eventQueue;
    eventQueue.add(event);

    // isPosting的作用是避免事件被重复post,从后面代码中可以看得出
    if (!postingState.isPosting) {
        // 根据Looper判断当前线程是否是Main线程
        postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
        // 设置为true,屏蔽重复调度post造成postSingleEvent被多次执行;下一次post会等待当前队列中所有事件被post之后才会继续处理
        postingState.isPosting = true;
        if (postingState.canceled) {
            throw new EventBusException("Internal error. Abort state was not reset");
        }
        try {
            // 可以看到将eventQueue中所有事件event进行处理
            while (!eventQueue.isEmpty()) {
            // 处理Event的函数
                postSingleEvent(eventQueue.remove(0), postingState);
            }
        } finally {
            postingState.isPosting = false;
            postingState.isMainThread = false;
        }
    }
}
    上面代码中主要是操作PostingThreadState对象postingState,该对象用来记录当前Event的Post状态,其中有个eventQueue变量用来存储当前线程中POST的Event。postingState通过ThreadLocal来保证线程安全;

    代码主要操作逻辑则较为简单,主要的工作是通过Looper判断当前运行线程是否为主线程,然后记录到postingState中;再将当前实践队列eventQueue中的所有event通过postSingleEvent进行处理;

    看到上面代码中,每一次post都会将当前eventQueue中的所有event Post出去,为避免eventQueue中的事件未处理完,下一次post操作又会操作eventQueue,因此会通过设置postingState中的isPosting变量来避免该情况,类似于加了锁,等当前post操作完成,将eventQueue中事件处理完,才允许下一个post操作运行。

    具体对事件event的处理逻辑在postSingleEvent方法中,如下所示:

2、EventBus#postSingleEvent:

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    Class<?> eventClass = event.getClass();
    boolean subscriptionFound = false;
    // 这里判断eventClass是否是继承类
    if (eventInheritance) {
        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
        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);
    }
    if (!subscriptionFound) {
        if (logNoSubscriberMessages) {
            Log.d(TAG, "No subscribers registered for event " + eventClass);
        }
        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                eventClass != SubscriberExceptionEvent.class) {
            post(new NoSubscriberEvent(this, event));
        }
    }
}
可以看到具体的处理逻辑在postSingleEventForEventType方法中;


3、EventBus#postSingleEventForEventType:

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
    CopyOnWriteArrayList<Subscription> subscriptions;

    // 前面register过程中将处理Event的方法信息存储到subscriptionsByEventType中,这里根据eventClass将其取出
    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;
            } finally {
                postingState.event = null;
                postingState.subscription = null;
                postingState.canceled = false;
            }
            if (aborted) {
                break;
            }
        }
        return true;
    }
    return false;
}
    上面的代码中用到了前面register过程中(suscribe方法中),将onEvent相关方法信息与其对应的处理EventClass信息存储到一个hashMap——subscriptionsByEventType中,通过key值即eventClass来查找出对应的onEvent方法,然后通过函数postToSubscription来处理。


4、EventBus#postToSubscription:

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
    // 根据onEvent方法的threadMode进行分别处理
    switch (subscription.subscriberMethod.threadMode) {
        case PostThread:
            invokeSubscriber(subscription, event);
            break;
        case MainThread:
            if (isMainThread) {
                invokeSubscriber(subscription, event);
            } else {
                mainThreadPoster.enqueue(subscription, event);
            }
            break;
        case BackgroundThread:
            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);
    }
}
     具体的处理逻辑很简单,可以看到是根据onEvent方法的threadMode不同进行分别处理;

1)PostThread则直接处理event;

2)MainThread则如果当前线程为UI线程,则直接进行处理,否则通过Handler机制发送给主线程;

private final de.greenrobot.event.HandlerPoster mainThreadPoster;
final class HandlerPoster extends Handler

3)BackGround则与MainThread进行相反的操作,表示事件处理在子线程中完成;注意backgroundPoster是个Runnable;

private final BackgroundPoster backgroundPoster;
final class BackgroundPoster implements Runnable

4)Async异步执行,则表示直接在子线程中处理事件;

private final AsyncPoster asyncPoster;
class AsyncPoster implements Runnable

AsyncPoster也是一个Runnable;

上面四种处理逻辑则对应了前面四种onEvent四种函数的具体使用环境与使用方法,可以根据具体需求进行选择使用。


5、EventBus#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);
    }
}
    具体的处理函数就是通过反射机制,method的invoke来执行具体的操作细节,这些操作细节是我们在onEvent方法中自己定义的;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值