EventBus源码解析

上一篇文章ButterKnife源码分析

EventBus适用于Android和Java的事件总线,简化了活动,碎片,线程,服务等之间的通信。减少代码,提高质量。EventBus主要用了观察者模式(也叫发布订阅者模式)实现代码之间的解耦。EventBus中提供异步的方式解决一个被观察者,多个被观察者,执行效率慢的问题。本文以3.1.1的源码为例。

EventBus的使用步骤和主要变量

使用的三步骤

//1 定义消息事件
public class MessageEvent { /* Additional fields if needed */ }

//2 
@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {/* Do something */};

 @Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }

//3
EventBus.getDefault().post(new MessageEvent());

ThreadMode:每个订阅方法都有一个线程模式,该模式决定EventBus将在哪个线程中调用该方法。

  • POSTING:那个线程发布事件,订阅者就在那个线程被调用;避免线程切换;不能做耗时操作,避免在主线程发布事件,阻塞主线程;
  • MAIN:在Android中订阅者将在主线程中被调用,1)如果在主线程中发布事件,就立即调用订阅者;2)不是在主线程中发布事件,将事件放入队列中依次发布。如果不是在Android中,MAIN和POSTING一样;
  • MAIN_ORDERED:在Android中,订阅者将在主线程中调用,和MAIN不同的是,事件加入队列依次发布,确保post不被阻塞;
  • BACKGROUND:在Android中,订阅者将在后台线程中调用。1)如果不在主线程不发布事件,订阅者就直接在当前线程调用;2)如果在主线程中发布事件,EventBus在同一个后台线程中将事件加入队列依次发布;
  • ASYNC:异步,订阅者在单独的线程中执行,可以执行耗时操作;EventBus使用线程池复用完成异步操作的线程;

EventBus的主要成员变量;

//key:事件的class,value:当前事件类的class,其实现的interface的class和其父类的class的集合;
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
//key:事件的class,value:事件的订阅者集合
 private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//key:订阅者,value:事件的集合;(一个订阅者多种不同的事件处理方法)
private final Map<Object, List<Class<?>>> typesBySubscriber;
//key:事件的class,value:事件对象;
private final Map<Class<?>, Object> stickyEvents;

//ThreadLocal每个线程的独有内存空间;线程安全,用空间换效率;常用在Handler中;不同线程发布的事件放入
//不同线程的threadLocal中,PostingThreadState中的eventQueue保存该线程发布的事件;
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
    @Override
    protected PostingThreadState initialValue() {
        return new PostingThreadState();
    }
};

EventBus的参数初始化;Poster的实现类在具体发布事件的时候,再细说;

EventBus(EventBusBuilder builder) {
    //在Android中mainThreadSupport不为null;不在Android中为null;
    mainThreadSupport = builder.getMainThreadSupport();
    //在Android中mainThreadPoster为HandlePoster实例;否则为null;
    mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
    backgroundPoster = new BackgroundPoster(this);
    asyncPoster = new AsyncPoster(this);
    //cache线程池,最大线程数为Interger.MAX_VALUE;
    executorService = builder.executorService;
}

getMainThreadSupport():创建AndroidHandlerMainThreadSupport的对象;

MainThreadSupport getMainThreadSupport() {
    //默认情况下为null;
    if (mainThreadSupport != null) {
        return mainThreadSupport;
    } else if (Logger.AndroidLogger.isAndroidLogAvailable()) {
        //调用Looper.getMainLooper(),获取mainLooper;
        Object looperOrNull = getAndroidMainLooperOrNull();
        return looperOrNull == null ? null :
                new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
    } else {
        return null;
    }
}
register的过程

先从register()方法开始,一旦订阅者注册接受事件,就必须通过unRegister()才不再接受事件;注册的过程中做了很多的处理,我们慢慢道来;

订阅者还必须有@Subscribe()注解的事件处理方法,可以通过threadMode,sticky,priority来配置;threadMode:决定EventBus在那个线程调用事件处理方法,默认是POSTING;sticky:是否是粘性事件,默认为false;priority:影响发布事件的顺序,默认值为0;

public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
    //找到订阅者类中定义的处理事件的方法(被@subscribe注解的方法);
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

findSubscriberMethods()找到被@Subscribe注解的方法(接受事件的方法);

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
    if (subscriberMethods != null) {
        return subscriberMethods;
    }
	//默认为false
    if (ignoreGeneratedIndex) {
        subscriberMethods = findUsingReflection(subscriberClass);
    } else {
        subscriberMethods = findUsingInfo(subscriberClass);
    }
    //如果订阅者类中没有定义被@subscribe注解的方法,报错;
    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;
    }
}

findUsingInfo():通过遍历找到订阅者或者其父类中的所有处理事件的方法;主要调用findUsingReflectionInSingleClass();

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
    FindState findState = prepareFindState();
    //初始化后,clazz为subscriberClass;subscriberInfo为null;
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        findState.subscriberInfo = getSubscriberInfo(findState);
        //默认为null
        if (findState.subscriberInfo != null) {
           
        } else {
            findUsingReflectionInSingleClass(findState);
        }
        //找到父类的clazz;
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}

findUsingReflectionInSingleClass():通过反射获取订阅者类中的所有方法,并遍历,找到对应的处理事件的方法(被@subscribe注解,是public的,不能被static,abstract修饰,并且只有一个参数),平时使用过程中,出现的异常信息,都可以在这个方法中找到。

private void findUsingReflectionInSingleClass(FindState findState) {
    //通过反射获取订阅者的所有方法;
    Method[] methods;
    try {
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
        methods = findState.clazz.getMethods();
        findState.skipSuperClasses = true;
    }
    //遍历方法,找到对应的处理事件的方法,并判断该方法是否符合要求;
    for (Method method : methods) {
        int modifiers = method.getModifiers();
        //判断修饰符
        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            //方法是否只有一个参数;
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 1) {
                //是否被@subscribe注解;
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                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()));
                    }
                }
            }
        }
    }
}

subscribe():将订阅者和事件关联起来,同时为事件的优先级给订阅者排序;最后如果事件是粘性的,会把之前缓存的事件再次发布个接受者

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    //事件的class;
    Class<?> eventType = subscriberMethod.eventType;
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    //找到当前事件的已有订阅者集合,为null,就创建;将当前订阅者加入集合中;
    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);
        }
    }

    //按优先级(priority)将订阅者排序,靠前的将优先执行;
    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);
    }
    subscribedEvents.add(eventType);

    //粘性事件,依然会将之前的粘性事件再次发布给订阅者;这就是粘性事件和普通事件的最大的区别;
    if (subscriberMethod.sticky) {
        //默认为true,
        if (eventInheritance) {
            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);
        }
    }
}

到此注册的过程就完成了,接下来看事件的发布过程,相对来说,比较简单些;

事件发布过程

事件的发布通常分为两种方式:发布普通事件和发布粘性事件;

1)发布普通事件

post():将当前事件发送到所在线程的ThreadLocal中的List中,按顺序将事件发送出去;

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

isMainThread():不是在Android中,mainThreadSupport为null,返回true;在Android中,发布事件是否在主线程中,在主线程中,为true,否者为false;

private boolean isMainThread() {
    return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true;
}

postSingleEvent():获取当前事件class对象、其的父类的class对象和其接口的class对象,遍历,发布事件;

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    Class<?> eventClass = event.getClass();
    boolean subscriptionFound = false;
    //默认为true;
    if (eventInheritance) {
        //将event类及其实现的接口和其父类存入List中;
        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
        int countTypes = eventTypes.size();
        for (int h = 0; h < countTypes; h++) {
            Class<?> clazz = eventTypes.get(h);
            //发布事件;如果postSingleEventForEventType()返回true,subscriptionFound就为true;
            subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
        }
    } else {
        subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
    }
}

postSingleEventForEventType():获取该事件的所有订阅者,向其发布事件;

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

2)发布粘性事件,除了要保存在stickyEvents中,其他的和发布普通的事件一样;

public void postSticky(Object event) {
    synchronized (stickyEvents) {
        //将当前粘性事件保存下来;订阅者可以通过getStickyEvent()获取到;
        stickyEvents.put(event.getClass(), event);
    }
    // Should be posted after it is putted, in case the subscriber wants to remove immediately
    post(event);
}

postToSubscription():是发布事件的核心方法;根据不同的threadMode参数和isMainThread选择不同的方式;

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:
            //Android环境中mainThreadPoster不为null;
            if (mainThreadPoster != null) {
                mainThreadPoster.enqueue(subscription, event);
            } else {
                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);
    }
}

Poster接口的具体实现类;

  • HandlePoster类:是Handler的子类,其Looper为mainLooper;handleMessage()方法中有个死循环,不断的从PendingPostQueue队列中取出事件发布;订阅者方法在主线程中调用,不能做耗时操作;
  • BackgroundPoster类:是个Runnable,run()方法中有个死循环,不断的发布事件;用线程池去执行BackgroundPoster,但是同一时间内最多只有一个runnable在执行;也就是说单独用一个线程不断的发布事件;
  • AsyncPoster类:也是一个Runnable,每当有消息加入,就用线程池去执行,完全异步;

PendingPostQueue:就是一个先进先出的队列,以单链表来实现的,线程安全;

Poster的具体实现类和PendingPostQueue可自行详细的看一下;

不管是那种方式发布事件,最终都会调用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);
    }
}
unregister()方法

unregister()方法比较简单,就是将当前订阅者删除;

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

EventBusAnnotationProcessor类主要是在编译阶段,生成对应的信息检索文件。

//支持的注解类型,Subscribe注解;
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
@SupportedOptions(value = {"eventBusIndex", "verbose"})
public class EventBusAnnotationProcessor extends AbstractProcessor {

	//annotations为支持的注解的集合;
	@Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
        Messager messager = processingEnv.getMessager();
        String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);
        
        //需要在项目的gradle中配置;
        if (index == null) {
         	messager.printMessage(Diagnostic.Kind.ERROR, "No option " + OPTION_EVENT_BUS_INDEX +
                        " passed to annotation processor");
             return false;
         }
        
        verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));
        int lastPeriod = index.lastIndexOf('.');
        String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;
        //遍历支持的注解的集合,找到被注解的方法,判断是否符合规则;
        //如:是否为public的,不能被static修饰等,必须有一个参数;满足条件的放入methodsByClass中;
        collectSubscribers(annotations, env, messager);
        checkForSubscribersToSkip(messager, indexPackage);
		
		//如果有订阅者处理事件的方法,生成信息检索文件;
        if (!methodsByClass.isEmpty()) {
        	createInfoIndexFile(index);
        }
        
        return true;
    }

index的值需要在项目的gradle中配置;如EventBusPerformance的build.gradle;生成的检索信息在build/generated/source/apt/debug/包名/目录下,类名为MyEventBusIndex的java文件;

defaultConfig {
    javaCompileOptions {
        annotationProcessorOptions {
            arguments = [eventBusIndex: 'org.greenrobot.eventbusperf.MyEventBusIndex']
        }
    }
}

以上就是EventBus源码分析的主要内容,如有问题,请多指教,谢谢!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值