手写实现EventBus


使用

github地址:

https://github.com/greenrobot/EventBus

引入

implementation 'org.greenrobot:eventbus:3.0.0'

订阅和接收

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    EventBus.getDefault().register(this);
}
 
@Override
protected void onDestroy() {
    super.onDestroy();
    EventBus.getDefault().unregister(this);
}

@Subscribe(threadMode = ThreadMode.MAIN,priority = 100,sticky = true)
public void onStringEvent(String event) {
    Log.d("接收者", "event----:" + event);
}

发布事件

EventBus.getDefault().post("我来发布消息");

发布粘性事件

EventBus.getDefault().postSticky("我来发布消息");

ThreadMode总共四个枚举项:

MAIN //UI主线程
BACKGROUND //后台线程
POSTING //和发布者处在同一个线程
ASYNC //异步线程

终止事件往下传递:

//优先级高的订阅者可以终止事件往下传递
EventBus.getDefault().cancelEventDelivery(event);

混淆

 -keepattributes *Annotation*
 -keepclassmembers class * {
     @org.greenrobot.eventbus.Subscribe <methods>;
 }
 -keep enum org.greenrobot.eventbus.ThreadMode { *; } 
 -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
     <init>(java.lang.Throwable);
 }

源码分析

第一步register

第一步:EventBus.getDefault().register(this);其中getDefault()获取单例,看EventBus中register()方法:

public void register(Object subscriber) {
    //首先获得class对象
    Class<?> subscriberClass = subscriber.getClass();
    //通过findSubscriberMethods来找到订阅者订阅了哪些事件,返回一个SubscriberMethod对象的List。
    //SubscriberMethod里包含了:这个对象的方法method、响应订阅的线程ThreadMode、方法参数类型eventType、订阅的优先级 priority、是否接收粘性sticky的boolean值。
    //其实就是解析这个类上的所有带@Subscriber注解的方法的属性。
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            // 订阅,第二步分析
            subscribe(subscriber, subscriberMethod);
        }
    }
}

看SubscriberMethodFinder类中findSubscriberMethods(Class<?> subscriberClass)方法:

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    // 先从缓存里面读取,订阅者的Class
    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
    if (subscriberMethods != null) {
        return subscriberMethods;
    }
    // ignoreGeneratedIndex属性表示是否忽略注解器生成的MyEventBusIndex。
    // 支持编译时注解的方式,需要引入eventbus的apt,ignoreGeneratedIndex的默认值为false,可以通过EventBusBuilder来设置它的值
    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;
    }
}

会走到SubscriberMethodFinder类中findUsingInfo(Class<?> subscriberClass)方法:

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
    // FindState涉及到享元设计模式
    FindState findState = prepareFindState();
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        //默认是空,除非用了编译时注解
        findState.subscriberInfo = getSubscriberInfo(findState);
        if (findState.subscriberInfo != null) {
            SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
            for (SubscriberMethod subscriberMethod : array) {
                if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                    findState.subscriberMethods.add(subscriberMethod);
                }
            }
        } else {
            //走到这里,通过反射去找
            findUsingReflectionInSingleClass(findState);
        }
        findState.moveToSuperclass();
    }
    // 释放 findState 享元模式
    return getMethodsAndRelease(findState);
}

走到SubscriberMethodFinder类中findUsingReflectionInSingleClass(FindState findState)方法:

//找方法的核心代码
private void findUsingReflectionInSingleClass(FindState findState) {
    Method[] methods;
    try {
        // 通过反射来获取订阅类的所有方法
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
        methods = findState.clazz.getMethods();
        findState.skipSuperClasses = true;
    }
    //for循环所有方法
    for (Method method : methods) {
        // 获取方法访问修饰符
        int modifiers = method.getModifiers();
        //找到所有声明为public的方法
        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            //获取参数的的Class
            Class<?>[] parameterTypes = method.getParameterTypes();
            //只允许包含一个参数
            if (parameterTypes.length == 1) {
                //Subscribe注解
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                if (subscribeAnnotation != null) {
                    //获取事件的Class ,也就是方法参数的Class
                    Class<?> eventType = parameterTypes[0];
                    // 检测添加
                    if (findState.checkAdd(method, eventType)) {
                        //获取ThreadMode
                        ThreadMode threadMode = subscribeAnnotation.threadMode();
                        // 往集合里面添加 SubscriberMethod ,解析方法注解所有的属性
                        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");
        }
    }
}

第一步总结:register()方法中调用findSubscriberMethods(),去解析注册者对象的所有方法,找出public方法,并且带有@Subscribe注解、并且参数只有一个,的方法,然后通过Annotation解析所有细节参数threadMode(线程)、priority(优先级)、sticky(是否粘性)、method(方法名)、eventType(方法参数类型),把这些参数封装成一个SubscriberMethod对象,添加到集合返回。

第二步register

EventBus中register()方法调用了subscribe(subscriber, subscriberMethod);其中subscriber就是register(this)中的this,subscriberMethod就是第一步中的集合遍历的元素对象。

EventBus中subscribe(Object subscriber, SubscriberMethod subscriberMethod)方法:

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    // 获取方法参数的class
    Class<?> eventType = subscriberMethod.eventType;
    // 创建一个 Subscription,subscribe方法的参数传给了Subscription
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    // 获取订阅了此事件类的所有订阅者信息列表,下面有分析subscriptionsByEventType
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    if (subscriptions == null) {
        // 线程安全的 ArrayList
        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;
        }
    }
    // 通过 subscriber 获取  List<Class<?>>,下面有分析typesBySubscriber
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    // 将此事件类加入 订阅者事件类列表中
    subscribedEvents.add(eventType);

    // 处理粘性事件
    if (subscriberMethod.sticky) {
        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);
        }
    }
}

查看subscriptionsByEventType,是EventBus的一个Map成员变量,可以根据EventType查找订阅事件

// key 是注解方法参数的class(eventType),value 存放的是Subscription的线程安全的集合列表
//Subscription 包含两个属性,一个是subscriber 订阅者(this),一个是SubscriberMethod注解方法的所有属性参数值(SubscriberMethod)
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;

查看typesBySubscriber,是EventBus的一个Map成员变量,根据我们的订阅对象找到EventType。

// key 是所有的订阅者(this),value 是所有订阅者里面方法的参数的class的集合
private final Map<Object, List<Class<?>>> typesBySubscriber;

粘性事件stickyEvents:是ConcurrentHashMap集合,粘性事件的缓存。

第二步总结:register()方法中调用subscribe方法,解析所有SubscriberMethod的eventType,然后按照要求解析成Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventTypeMap<Object, List<Class<?>>> typesBySubscriber

第三步post

查看EventBus中post方法:

public void post(Object event) {
    // currentPostingThreadState是一个 ThreadLocal,他的特点是获取当前线程一份独有的变量数据,不受其他线程影响。
    PostingThreadState postingState = currentPostingThreadState.get();
    // postingState 就是获取到的线程独有的变量数据
    List<Object> eventQueue = postingState.eventQueue;
    // 把post的事件添加到事件队列
    eventQueue.add(event);
    // 如果没有处在事件发布状态,那么开始发送事件并一直保持发布状态
    if (!postingState.isPosting) {
        //是否是主线程
        postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
        //isPosting = true
        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 final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
    @Override
    protected PostingThreadState initialValue() {
        return new PostingThreadState();
    }
};

查看EventBus中postSingleEvent方法:

//参数event是post的对象
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    //得到事件的Class
    Class<?> eventClass = event.getClass();
    //是否找到订阅者
    boolean subscriptionFound = false;
    //如果支持事件继承,默认为支持
    if (eventInheritance) {
        //查找 eventClass 的所有父类和接口
        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
        int countTypes = eventTypes.size();
        for (int h = 0; h < countTypes; h++) {
            Class<?> clazz = eventTypes.get(h);
            // 依次向 eventClass 的父类或接口的订阅方法发送事件
            // 只要有一个事件发送成功,返回 true ,那么 subscriptionFound 就为 true,下面有分析
            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));
        }
    }
}

查看EventBus中postSingleEventForEventType方法:

//event是post的对象,eventClass是post的对象的class
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
    CopyOnWriteArrayList<Subscription> subscriptions;
    synchronized (this) {
        // subscriptionsByEventType是第二步中的map,得到Subscription集合List
        subscriptions = subscriptionsByEventType.get(eventClass);
    }
    if (subscriptions != null && !subscriptions.isEmpty()) {
        // 遍历subscriptions
        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;
}

查看EventBus中postToSubscription方法:

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

第三步总结:post()方法中去遍历了subscriptionsByEventType,找到符合的方法,调用方法的method.invoke()执行。

第四步unregister

unregister就是移除。查看EventBus中unregister方法:

public synchronized void unregister(Object subscriber) {
    // 获取订阅对象的所有订阅事件类列表,第二步中的map
    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());
    }
}

查看EventBus中unsubscribeByEventType方法:

private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
    // 获取事件类的所有订阅信息列表,将订阅信息从订阅信息集合中移除,同时将订阅信息中的active属性置为FALSE,第二步中的map
    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) {
                // 将订阅信息激活状态置为FALSE
                subscription.active = false;
                // 将订阅信息从集合中移除
                subscriptions.remove(i);
                i--;
                size--;
            }
        }
    }
}

手写实现

https://github.com/AdamRight/TeaTool/blob/master/app/src/main/java/com/tea/teatool/teaeventbus


文章作者:
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 !
  目录