EventBus 学习笔记

REGISTER分析

EventBus.getDefault()

static volatile EventBus defaultInstance;
/** 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;
}
复制代码

采用double check方式创建EventBus单例。

register(this)

public void register(Object subscriber) {
    //反射调用,获取订阅者的类对象
    Class<?> subscriberClass = subscriber.getClass();
    //获取订阅者所有的订阅方法以@Subscribe为注解的一些public方法
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    
    //依次注册这些订阅方法
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            //对订阅方法进行注册
            subscribe(subscriber, subscriberMethod);
        }
    }
}
复制代码

SubscriberMethod.class

public class SubscriberMethod {
    final Method method; //方法
    final ThreadMode threadMode; //执行线程
    final Class<?> eventType; //接收的事件类型
    final int priority; //优先级
    final boolean sticky; //粘性事件
    /** Used for efficient comparison */
    String methodString;
    
    //...省略部分代码
}
复制代码

SubscriberMethod是一个订阅方法的实体类,里面存储了订阅方法的一些基本信息,订阅方法就是在类中以@Subscribe为注解的一些public方法,注意是public方法否则会报错。

然后进入subscriberMethodFinder.findSubscriberMethods(subscriberClass),该代码的作用主要是获取当前类中所有的订阅方法。 SubscriberMethodFinder.findSubscriberMethods()

private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();//保存有订阅功能的Class和该类中的订阅方法

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    
    //从缓存中获取订阅方法
    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
    
    if (subscriberMethods != null) {
        return subscriberMethods;
    }
    
    //是否忽略注解器生成的MyEventBusIndex类
    if (ignoreGeneratedIndex) {
        //利用反射来获取订阅类中的订阅方法信息
        subscriberMethods = findUsingReflection(subscriberClass);
    } else {
        //从注解器生成的MyEventBusIndex类中获得订阅类的订阅方法信息
        subscriberMethods = findUsingInfo(subscriberClass);
    }
    //当前类中没有订阅方法
    if (subscriberMethods.isEmpty()) {
        throw new EventBusException("Subscriber " + subscriberClass
                + " and its super classes have no public methods with the @Subscribe annotation");
    } else {
        //保存进缓存
        METHOD_CACHE.put(subscriberClass, subscriberMethods);
        return subscriberMethods;
    }
}
复制代码

对于获取我们注册的订阅方法,首先就是通过缓存来获取,如果没有的话则通过以下两种方式进行获取:

1.EventBusAnnotationProcessor注解生成器在编译期通过读取@Subscribe()注解并解析,处理其中所包含的信息,然后生成java类来保存所有订阅者关于订阅的信息。

2.运行时使用反射来获得这些订阅者的信息

private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
    //FindState其实就是一个里面保存了订阅者和订阅方法信息的一个实体类,包括订阅类中所有订阅的事件类型和所有的订阅方法等。
    FindState findState = prepareFindState();
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        
        //获取订阅方法
        findUsingReflectionInSingleClass(findState);
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}
复制代码
private static final int POOL_SIZE = 4;
    private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];//对象池,大小为4,保存复用FindState对象

private FindState prepareFindState() {
    synchronized (FIND_STATE_POOL) {
        for (int i = 0; i < POOL_SIZE; i++) {
            FindState state = FIND_STATE_POOL[i];
            if (state != null) {
                FIND_STATE_POOL[i] = null;
                return state;
            }
        }
    }
    return new FindState();
} 
复制代码
static class FindState {
	//订阅方法
    final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
    //以event为key,以method为value
    final Map<Class, Object> anyMethodByEventType = new HashMap<>();
    //以method的名字生成一个methodKey为key,该method的类(订阅者)为value
    final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
    final StringBuilder methodKeyBuilder = new StringBuilder(128);
    Class<?> subscriberClass;
    Class<?> clazz;
    boolean skipSuperClasses;
    SubscriberInfo subscriberInfo;
	//...省略部分代码
	
    void initForSubscriber(Class<?> subscriberClass) {
        this.subscriberClass = clazz = subscriberClass;
        skipSuperClasses = false;
        subscriberInfo = null;
    }
    
    void moveToSuperclass() {
        if (skipSuperClasses) {
            clazz = null;
        } else {
            clazz = clazz.getSuperclass();
            String clazzName = clazz.getName();
            /** Skip system classes, this just degrades performance. */
            if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
                clazz = null;
            }
        }
    }
}
复制代码

FindState其实就是一个里面保存了订阅者和订阅方法信息的一个实体类,包括订阅类中所有订阅的事件类型和所有的订阅方法等。

private void findUsingReflectionInSingleClass(FindState findState) {
    //方法
    Method[] methods;
    try {
        
        //获取当前类中所有的方法
        // This is faster than getMethods, especially when subscribers are fat classes like Activities
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
        // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
        methods = findState.clazz.getMethods();
        findState.skipSuperClasses = true;
    }
    //遍历所有方法
    for (Method method : methods) {

        //获取方法的访问修饰权
        int modifiers = method.getModifiers();
        //订阅方法必须是must be public, non-static, and non-abstract
        
            //获取订阅方法参数类型
            Class<?>[] parameterTypes = method.getParameterTypes();
            //注解方法必须只有一个参数
            if (parameterTypes.length == 1) {
                //获取订阅方法的注解
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                //该订阅方法包含Subscribe注解
                if (subscribeAnnotation != null) {
                    Class<?> eventType = parameterTypes[0];
                    //添加该注解方法
                    if (findState.checkAdd(method, eventType)) {
                        //该注解方法的线程模式
                        ThreadMode threadMode = subscribeAnnotation.threadMode();
                        //添加该注解方法
                        findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                    }
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException("@Subscribe method " + methodName +
                        "must have exactly 1 parameter but has " + parameterTypes.length);
            }
        } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
            String methodName = method.getDeclaringClass().getName() + "." + method.getName();
            throw new EventBusException(methodName +
                    " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
        }
    }
}
复制代码

首先会得到订阅类的class对象并通过反射获取订阅类中的所有方法信息,然后通过筛选获取到订阅方法集合。这里面就解释了为什么要以@Subscribe为注解的方法,且必须是public类型,方法参数只有一个的原因。

回收FindState对象,放入对象池中。

private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
    List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
    findState.recycle();
    synchronized (FIND_STATE_POOL) {
        for (int i = 0; i < POOL_SIZE; i++) {
            if (FIND_STATE_POOL[i] == null) {
                FIND_STATE_POOL[i] = findState;
                break;
            }
        }
    }
    return subscriberMethods;
}
复制代码

Subscribe.java

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface Subscribe {
        ThreadMode threadMode() default ThreadMode.POSTING;
        /**
         * If true, delivers the most recent sticky event (posted with
         * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
         */
        boolean sticky() default false;
        /** Subscriber priority to influence the order of event delivery.
         * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
         * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
         * delivery among subscribers with different {@link ThreadMode}s! */
        int priority() default 0;
    }
复制代码

注解,分为三种参数

ThreadMode,方法执行的线程,POSTING(默认值)、MAIN、BACKGROUND、ASYNC

sticky,粘性时间,默认值false

priority,优先级,默认值0
复制代码

该方法流程是:

1.拿到当前 class 的所有方法

2.过滤掉不是 public 和是 abstract、static、bridge、synthetic 的方法

3.过滤出方法参数只有一个的方法

4.过滤出被Subscribe注解修饰的方法

5.将 method 方法和 event 事件添加到 findState 中

6.将 EventBus 关心的 method 方法、event 事件、threadMode、priority、sticky 封装成SubscriberMethod 对象添加到 findState.subscriberMethods 列表中

subscribe()

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;//保存事件Class与订阅类和订阅类的订阅方法的对象Class的映射

private final Map<Object, List<Class<?>>> typesBySubscriber;//保存订阅类和订阅类的订阅方法的对象Class和事件Class的映射

private final Map<Class<?>, Object> stickyEvents;//存放sticky事件Class与sticky事件对象的映射

// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    
    //订阅方法的参数类型,也是事件类型
    Class<?> eventType = subscriberMethod.eventType;
    //订阅方法描述,实体类(当前类中的订阅方法)
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    //获取当前类中的所有订阅方法
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    //该订阅方法还没有进行注册
    if (subscriptions == null) {
        subscriptions = new CopyOnWriteArrayList<>();
        //注册该订阅方法
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        
        //已经注册了,报异常
        if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                    + eventType);
        }
    }
    //总的所有的订阅方法
    int size = subscriptions.size();
    for (int i = 0; i <= size; i++) {
        
        //根据优先级,将订阅者插入到指定的位置
        if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }
    //获取订阅者所有订阅的事件类型
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    //将该事件类型添加到typesBySubscriber中
    subscribedEvents.add(eventType);
    //如果接收sticky事件,立即分发sticky事件
    if (subscriberMethod.sticky) {
        if (eventInheritance) {
            // Existing sticky events of all subclasses of eventType have to be considered.
            // Note: Iterating over all events may be inefficient with lots of sticky events,
            // thus data structure should be changed to allow a more efficient lookup
            // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
            Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
            for (Map.Entry<Class<?>, Object> entry : entries) {
                Class<?> candidateEventType = entry.getKey();
                if (eventType.isAssignableFrom(candidateEventType)) {
                    Object stickyEvent = entry.getValue();
                    checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                }
            }
        } else {
            Object stickyEvent = stickyEvents.get(eventType);
            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
        }
    }
}
复制代码

Subscription.java

//订阅者信息 
final class Subscription {
    final Object subscriber;//订阅者
    final SubscriberMethod subscriberMethod;//订阅方法
}
复制代码
//subscriptionsByEventType,key订阅方法类型 values 所有订阅了该类型的订阅者集合
Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//typesBySubscriber,key订阅者 values订阅事件集合
Map<Object, List<Class<?>>> typesBySubscriber;
复制代码

1.首先获取订阅方法的参数类型即订阅事件类型

2.根据订阅事件类型获取该事件类型的所有订阅者

3.将该订阅者添加到该事件类型的订阅者集合中即:subscriptionsByEventType

4.获取订阅者所有的订阅事件类型

5.将该事件类型添加到该订阅者的订阅事件类型集中即:typesBySubscriber

事件POST分析

EventBus.getDefault().post(new MessageEvent(""));

    /** Posts the given event to the event bus. */
    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);
        if (!postingState.isPosting) {
            postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
            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;
            }
        }
    }
复制代码

PostingThreadState.class

    /** For ThreadLocal, much faster to set (and get multiple values). */
    final static class PostingThreadState {
	    //当前线程的事件队列
        final List<Object> eventQueue = new ArrayList<Object>();
        //是否有事件正在分发
        boolean isPosting;
        //post的线程是否是主线程
        boolean isMainThread;
        Subscription subscription;
        Object event;
        boolean canceled;
    }
复制代码

PostingThreadState中包含了当前线程的事件队列,就是当前线程所有分发的事件都保存在eventQueue事件队列中以及订阅者订阅事件等信息,有了这些信息我们就可以从事件队列中取出事件分发给对应的订阅者。 PostingThreadState postingState = currentPostingThreadState.get();

    private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };
复制代码

ThreadLocal 是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,而这段数据是不会与其他线程共享的。可以看出currentPostingThreadState的实现是一个包含了PostingThreadState的ThreadLocal对象,这样可以保证取到的都是自己线程对应的数据。 postSingleEvent(eventQueue.remove(0), postingState);

    //对事件进行分发
    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        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));
            }
        }
    }
复制代码
    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;
                } finally {
                    postingState.event = null;
                    postingState.subscription = null;
                    postingState.canceled = false;
                }
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }
    //将事件分发给对应的订阅者
    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);
        }
    }
复制代码
    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);
        }
    }
复制代码

1.首先获取当前线程的PostingThreadState对象从而获取到当前线程的事件队列

2.通过事件类型获取到所有订阅者集合

3.通过反射执行订阅者中的订阅方法

EventBus允许事件接收者用如下几个模式来对事件进行处理,即:POSTING、MAIN、MAIN_ORDER、BACKGROUND、ASYNC。

BACKGROUND

订阅者

@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEventBackgroundThread(Integer event) {
}
复制代码

处理方式

//EventBus 对BACKGROUND 模式的处理
case BACKGROUND:
     if (isMainThread) {//如果是UI线程,则开启新线程执行之。
        backgroundPoster.enqueue(subscription, event);
     } else {//非UI线程则在直接在本线程中执行
         invokeSubscriber(subscription, event);
     }
break;
复制代码
private final HandlerPoster mainThreadPoster;
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
复制代码
//注意BackgroundPoster是一个Runnable
final class BackgroundPoster implements Runnable {

    private final PendingPostQueue queue;//事件链表
    private final EventBus eventBus;
    //volatile确保可见性,但是不能保证原子性
    //判断事件是否得到执行
    private volatile boolean executorRunning;

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

    public void enqueue(Subscription subscription, Object event) {
        //1、获取一个pendingPost
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            //2、构建事件链表
            queue.enqueue(pendingPost);
            //3、执行事件
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);
            }
        }
    }
    
    @Override
    public void run() {
        try {
            try {
                //循环获取链表,并处理直到链表为null
                while (true) {
                    //1、从连表中获取一个PendingPost,链表为null则等待一秒
                    PendingPost pendingPost = queue.poll(1000);
                    if (pendingPost == null) {
                        synchronized (this) {
                            // Check again, this time in synchronized
                            //继续获取pendingPost
                            pendingPost = queue.poll();
                            //如果还为null,认定此时没有事件产生
                            if (pendingPost == null) {
                                executorRunning = false;
                                //退出run方法
                                return;
                            }
                        }
                    }
                    //在这里会调用PendingPost.releasePendingPost
                    eventBus.invokeSubscriber(pendingPost);
                }
            } catch (InterruptedException e) {
                Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }
}
复制代码

在while循环中,先调用poll(1000)方法,如果事件链表为null,则wait(1000),等待事件产生;而后再次在用poll()获取,如果此时仍然为null,则EventBus认为现阶段没有事件,则run方法执行结束,直到下次事件来临后继续调用eventBus.getExecutorService().execute(this)执行。

private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
复制代码

eventBus.getExecutorService()方法返回的是在构造EventBus时创建的线程池。

还需要注意的是因为在fun方法中循环便利事件链表,所以为了防止事件阻塞,在使用ThreadModel.BACKGROUND的时候,要求此@Subricebe 方法不要执行耗时的逻辑。比如网络请求等。

耗时的逻辑用ThreadModel.ASYNC 模式,因为该模式很简单就是获取链表中的一个事件,执行之;而不像BackGround那样循环整个事件链表挨个执行之。

//AsyncPoster的run方法
public void run() {
    PendingPost pendingPost = queue.poll();
    if(pendingPost == null) {
        throw new IllegalStateException("No pending post available");
    }
    eventBus.invokeSubscriber(pendingPost);
}
复制代码
 case MAIN:
   if (isMainThread) {
        //1、如果已经处于UI线程,则直接调用
        invokeSubscriber(subscription, event);
    } else {
        //2、如果非UI线程,则调用mainThreadPoster处理
        mainThreadPoster.enqueue(subscription, event);
    }
    break;
复制代码

HandlerPoster对应的就是ThreadModel.MAIN,表明是在UI线程中获取PendingPostQueue链表中的元素(PendingPost对象)进行处理。

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 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);
                //如果在规定的时间内还没有处理完毕,则继续回调handleMessage处理
                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;
        }
    }
}
复制代码

可以看出handleMessage对事件链表的处理是不断循环获取链表中的PendingPost,当链表中的事件处理完毕后退出while循环。或者是在规定的时间内maxMillisInsideHandleMessage没有将事件处理完,则继续调用sendMessage。继而重新回调handleMessage方法,事件会继续执行。这是为了避免队列过长或者事件耗时较长时,while循环阻塞主线程造成卡顿。

在EventBus 中除了用HandlerPoster默认实现将事件切换到主线程执行之外,EventBus还提供了MainThreadSupport这个接口:

public interface MainThreadSupport {

    boolean isMainThread();
    //返回客户端自定义的ThreadModel.MAIN处理方式
    Poster createPoster(EventBus 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) {
        //默认使用HandlerPoster对象
        return new HandlerPoster(eventBus, looper, 10);
    }
}
复制代码
class PendingPost {
    //PendingPost集合
    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();
    //具体的事件对象
    Object event;
    Subscription subscription;
    
    //next指针
    PendingPost next;
    
    private PendingPost(Object event, Subscription subscription) {
        this.event = event;
        this.subscription = subscription;
    }

    static PendingPost obtainPendingPost(Subscription subscription, Object event) {
        //从pendingPostPool获取一个PendingPost
        synchronized (pendingPostPool) {
            int size = pendingPostPool.size();
            //从集合末尾获取一个
            if (size > 0) {
                PendingPost pendingPost = pendingPostPool.remove(size - 1);
                pendingPost.event = event;
                pendingPost.subscription = subscription;
                pendingPost.next = null;
                return pendingPost;
            }
        }
        //如果pendingPostPool没有,则创建一个
        return new PendingPost(event, subscription);
    }
    //事件处理完毕后,此时调用PendingPost的releasePendingPost静态方法将PendingPost对象回收
    static void releasePendingPost(PendingPost pendingPost) {
        //数据置空
        pendingPost.event = null;
        pendingPost.subscription = null;
        pendingPost.next = null;
        synchronized (pendingPostPool) {
            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
    }
}
复制代码

可以看出PendingPost除了封装了事件对象event,事件接收者对象Subscription之外,还弄了个next引用,这明白着就是构建一个链表结构,注意该类还有个静态的pendingPostPool集合,该集合包含了PendingPost对象。

首先所以我们来看看EventBus是怎么构建这个PendingPost链表的,具体的构建过程在PendingPostQueue类里面,先瞧瞧这个类有啥:

final class PendingPostQueue {
    private PendingPost head;//链表头部引用
    private PendingPost tail;//链表尾部指针

    synchronized void enqueue(PendingPost pendingPost) {
        if (pendingPost == null) {
            throw new NullPointerException("null cannot be enqueued");
        }
        if (tail != null) {
            tail.next = pendingPost;
            tail = pendingPost;
        } else if (head == null) {
            head = tail = pendingPost;//第一次执行是走这个分支
        } else {
            throw new IllegalStateException("Head present, but no tail");
        }
        notifyAll();//唤醒等待的线程
    }

    synchronized PendingPost poll() {
        PendingPost pendingPost = head;//返回head节点,并将head指针下移
        if (head != null) {
            head = head.next;
            if (head == null) {
                tail = null;
            }
        }
        return pendingPost;
    }

    synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
        if (head == null) {
            wait(maxMillisToWait);//列表为空,等待并释放锁
        }
        return poll();
    }
}
复制代码

enqueue方法的作用就是将EventBus post的事件形成一个链表。然后通过PendingPostQueue的poll方法获取链表中的对象。

PendingPostQueue的作用就是构建链表和从链表中获取PendingPost的过程,且在构建的过程中如果构建完毕则调用notifyAll,取PendingPost的时候如果链表为null则wait ,可以说是一个简单的生产者消费者模式。

事件UNREGISTER

    /** Unregisters the given subscriber from all event classes. */
   public synchronized void unregister(Object subscriber) {
      //获取订阅者的所有订阅的事件类型
       List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
       if (subscribedTypes != null) {
           for (Class<?> eventType : subscribedTypes) {
           //从事件类型的订阅者集合中移除订阅者
               unsubscribeByEventType(subscriber, eventType);
           }
           typesBySubscriber.remove(subscriber);
       } else {
           Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
       }
   }
复制代码
    /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
    private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
     //获取事件类型的所有订阅者
        List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        //遍历订阅者集合,将解除的订阅者移除
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }
复制代码

1.首先获取订阅者的所有订阅事件

2.遍历订阅事件

3.根据订阅事件获取所有的订阅了该事件的订阅者集合

4.将该订阅者移除

5.将步骤1中的集合中的订阅者移除

总结

register

1、首先用register()方法注册一个订阅者

2、获取该订阅者的所有订阅的方法

3、根据该订阅者的所有订阅的事件类型,将订阅者存入到每个以 事件类型为key 以所有订阅者为values的map集合中

4、然后将订阅事件添加到以订阅者为key 以订阅者所有订阅事件为values的map集合中

4.1、如果是订阅了粘滞事件的订阅者,从粘滞事件缓存区获取之前发送过的粘滞事件,响应这些粘滞事件。

post

1、首先获取当前线程的事件队列

2、将要发送的事件添加到事件队列中

3、根据发送事件类型获取所有的订阅者

4、根据响应方法的执行模式,在相应线程通过反射执行订阅者的订阅方法

unregister

1、首先通过unregister方法拿到要取消的订阅者

2、得到该订阅者的所有订阅事件类型

3、遍历事件类型,根据每个事件类型获取到所有的订阅者集合,并从集合中删除该订阅者

4、将订阅者从步骤2的集合中移除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值