Android | EventBus源码分析

  • Post author:
  • Post category:其他




前言

EventBus是一种用于Android的发布/订阅事件总线。它有很多优点:简化应用组件间的通信;解耦事件的发送者和接收者;避免复杂和容易出错的依赖和生命周期的问题;很快,专门为高性能优化过等等。



基础知识

EventBus的基础知识和使用详解可以阅读这篇文章:

EventBus使用详解



源码分析

EventBus源码分析主要分为两个过程:

  1. 订阅事件
  2. 发布事件

在分析订阅事件之前,我们先来分析一下与订阅事件相关的订阅者索引。



订阅者索引

默认情况下,EventBus使用Java反射来查找订阅者信息。订阅者索引是EventBus 3的一个新特性。它可以加速查找订阅者信息的过程,是一个可选的优化。订阅者索引的原理是:使用EventBus的注解处理器在应用构建期间创建订阅者索引类,该类已经包含了所有的订阅者信息。EventBus官方推荐在Android中使用订阅者索引以获得最佳的性能。

要开启订阅者索引的生成,你需要在构建脚本中使用annotationProcessor属性将EventBus的注解处理器添加到应用的构建中,还要设置一个eventBusIndex参数来指定要生成的订阅者索引的完全限定类名。

首先,修改模块下的build.gradle构建脚本。如下所示:

android {
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [eventBusIndex: 'com.github.cyc.eventbus.subscriberindexdemo.MyEventBusIndex']
            }
        }
    }
    ...
}

dependencies {
    ...
    compile 'org.greenrobot:eventbus:3.1.1'
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}

然后,build一下工程。EventBus注解处理器将为你生成一个订阅者索引类。示例代码如下所示:

package com.github.cyc.eventbus.subscriberindexdemo;

import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberMethodInfo;
import org.greenrobot.eventbus.meta.SubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;

import org.greenrobot.eventbus.ThreadMode;

import java.util.HashMap;
import java.util.Map;

/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
   
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;

    static {
   
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();

        putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
   
            new SubscriberMethodInfo("onMessageEvent", MessageEvent.class, ThreadMode.MAIN),
        }));

    }

    private static void putIndex(SubscriberInfo info) {
   
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }

    @Override
    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
   
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
   
            return info;
        } else {
   
            return null;
        }
    }
}

可以看到,所有的订阅者信息都先被保存在SUBSCRIBER_INDEX静态成员变量中。后面查找订阅者信息时,EventBus就可以直接调用getSubscriberInfo()方法来获取该订阅者的信息了。

最后,在应用自定义的Application类的onCreate()方法中将订阅者索引添加到EventBus中,并将该EventBus设置成默认的EventBus。示例代码如下所示:

public class MyApplication extends Application {
   

    @Override
    public void onCreate() {
   
        super.onCreate();
        // 配置EventBus
        EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
    }
}

我们来看builder()、addIndex()和installDefaultEventBus()方法的代码:

public class EventBus {
   
    static volatile EventBus defaultInstance;
    ...
    
    public static EventBusBuilder builder() {
   
        return new EventBusBuilder();
    }    
}

public class EventBusBuilder {
   
    ...
    List<SubscriberInfoIndex> subscriberInfoIndexes;

    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
   
        if (subscriberInfoIndexes == null) {
   
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }
    
    public EventBus installDefaultEventBus() {
   
        synchronized (EventBus.class) {
   
            if (EventBus.defaultInstance != null) {
   
                throw new EventBusException("Default instance already exists." +
                        " It may be only set once before it's used the first time to ensure consistent behavior.");
            }
            EventBus.defaultInstance = build();
            return EventBus.defaultInstance;
        }
    }    
    
    public EventBus build() {
   
        return new EventBus(this);
    }    
}

builder()静态方法新建了一个EventBusBuilder对象。addIndex()方法将生成的订阅者索引添加到EventBusBuilder对象的subscriberInfoIndexes成员变量中。installDefaultEventBus()方法调用了build()方法新建了一个EventBus对象,并将该对象赋值给EventBus的defaultInstance静态成员变量。这样,后面调用EventBus.getDefault()静态方法获取到的就是该EventBus对象了。我们接着来看EventBus.getDefault()静态方法的代码:

public class EventBus {
   
    static volatile EventBus defaultInstance;

    private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
    
    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    private final Map<Object, List<Class<?>>> typesBySubscriber;
    private final Map<Class<?>, Object> stickyEvents;
    
    private final Poster mainThreadPoster;
    private final BackgroundPoster backgroundPoster;
    private final AsyncPoster asyncPoster;
    private final SubscriberMethodFinder subscriberMethodFinder;
    ...

    public static EventBus getDefault() {
   
        if (defaultInstance == null) {
   
            synchronized (EventBus.class) {
   
                if (defaultInstance == null) {
   
                    defaultInstance = new EventBus(



版权声明:本文为u012317510原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。