EventBus3.0的使用及源码分析

一、首先,EventBus 3.0的简单使用:

1、首先在Activity的对应生命周期中进行注册和解绑
@Override
protected void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
protected void onStop() {
    super.onStop();
    EventBus.getDefault().unregister(this);
}
2、发送: 定义一个指定的事件,并且在需要的位置去发送该事件:

事件

public class MessageEvent {
    public String message;

    public MessageEvent(String message) {
                 this.message = message;
         }
}

发送:主线程发送:

public void postMain(View view) {
    EventBus.getDefault().post(new MessageEvent("主线程发送的事件"));
}
3、接收:接收事件的方法要用 @Subscribe 注解标注
@Subscribe
public void receiveMessageEvent(MessageEvent messageEvent) {
    mTvText.setText("接收到:  " + messageEvent.message + "  线程名称: " +  Thread.currentThread().getName());
}
4、ThreadMode: 指定接收事件的执行线程

EventBus通过枚举指定了五个线程模式:
- POSTING:订阅事件的线程 与发布事件的线程一样。
- MAIN:订阅事件会在主线程中执行
- MAIN_ORDERED:订阅事件会在主线程执行。如果您在一个带有主线程的事件处理程序中发布另一个事件,第一个事件处理程序将完成,然后在稍后的时间点调用第二个事件处理程序(当主线程有容量时)
- BACKGROUND:如果发布线程不是主线程,则订阅事件会直接在该线程被调用,如果发布线程时在主线程,则使用一个独立的线程去处理订阅事件。
- ASYNC:订阅事件的处理在一个独立的线程中执行,总是独立于发布事件的线程和主线程

例如。你想让接收事件的处理在主线程中执行:

@Subscribe(threadMode = ThreadMode.MAIN)
public void receiveMessageEvent(MessageEvent messageEvent) {
    mTvText.setText("接收到:  " + messageEvent.message + "  线程名称: " + Thread.currentThread().getName());
}
5、priority:优先级

说明: 为int类型, 默认priority为0。这个是相对同一个事件,不同订阅者接收该事件的优先级。优先级越高的订阅者越先接收到事件。

 @Subscribe(priority = 3)
    public void receiveMessageEvent(final MessageEvent messageEvent) {
            Log.d("===", "MainActivity接收到:  " + messageEvent.message + "  线程名称: " + Thread.currentThread().getName());
    }
6、Sticky: 粘性事件

说明: 假如你想先发送了事件,但我等到需要时在接收,这是就需要用到Sticky。首先你需要通过postSticky来发送事件,然后你再在需要接收事件时注册EventBus,然后处理事件的方法要在注解中使用sticky = true。
例如:

public class StickyActivity extends AppCompatActivity {

    private TextView mTvText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sticky);
        mTvText = findViewById(R.id.tv_text);

        //发送粘性事件: 注意使用的是posoSticky方法
        EventBus.getDefault().postSticky(new MessageEvent("粘性事件"));

    }


    //点击在注册,在发送事件之后
    public void resister(View view) {
        EventBus.getDefault().register(this);

    }


    //需要在注解中设置sticy = true
    @Subscribe(sticky = true)
    public void receiveEvent(MessageEvent messageEvent) {
        mTvText.setText(messageEvent.message);
        Log.d("===", "StickyActivity接收到:  " + messageEvent.message + "  线程名称: " + Thread.currentThread().getName());

    }

@Override
protected void onStop() {
    super.onStop();
    //注意这里比普通的事件多了一步,就是需要把所有的粘性事件remove掉
    EventBus.getDefault().removeAllStickyEvents();
    EventBus.getDefault().unregister(this);

}


    public class MessageEvent {

        String message;

        public MessageEvent(String message) {
            this.message = message;
        }
    }

}


二、开始看EventBus的订阅的源码:

1、首先看EventBus的初始化操作 EventBus.getDefault():
public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

可以看到EventBus的生成使用了双重锁的懒汉单例模式,保证全局只有一个EventBus实例,整个项目的事件发送和订阅都有改实例去管理。
这里注意下EventBus里面的几个重要参数,下面会用到:

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;   //根绝事件类型保存的订阅信息Subscription(属性包括订阅者和订阅方法) 的map
private final Map<Object, List<Class<?>>> typesBySubscriber; //根据订阅者进行保存的所有订阅方法的map
private final Map<Class<?>, Object> stickyEvents;//所有的粘性事件
2、然后我们再来分析register方法
public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();

   //通过这个subscriberMethodFinder去找到订阅者(例子中的Activity)所有的订阅方法(用Subscribe注解标明的方法)
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

可以看到通过 subscriber.getClass()拿到订阅者的Class对象,然后利用subscriberMethodFinder去拿到订阅者的所有订阅方法(用Subscribe注解标明的方法),然后进行遍历,调用 subscribe(subscriber, subscriberMethod)。

首先我们看下这个SubscriberMethod 是什么东东?

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 其实就是保存订阅方法的一些属性的对象。

3、好了,可以看到这个SubscriberMethod 其实就是保存订阅方法的一些属性的对象。
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    //通过缓存去拿到订阅者的所有订阅方法,注意看 METHOD_CACHE 为Map<Class<?>, List<SubscriberMethod>> 类型
    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;
    }
}

从上面看到这里利用了缓存机制,保存这个每个订阅者对应的订阅方法。
缓存为空时,判断是从注解器生成的类去获取还是通过反射去获取。众所周知,利用反射使比较耗性能的,所以EventBus 3.0 之后添加了利用注解器去获取(注解处理器是在编译时扫描和编译和处理注解,而反射是在运行时,这里就可以知道为什么注解器的比反射效率高了吧。
关于注解处理器的详细知识可以参考这篇博文,里面写的非常祥细:Java注解处理器

4、我们这里先看通过反射去获取订阅方法 findUsingReflection(subscriberClass) 的代码:
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
    //获取FindState
    FindState findState = prepareFindState();
    //把订阅者和FindState关联起来
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        findUsingReflectionInSingleClass(findState);
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}

然后我们来看看这个FindState是什么鬼?

static class FindState {
    // 所有的订阅方法
    final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
     //根据每种事件保存对应的订阅方法的Map
    final Map<Class, Object> anyMethodByEventType = new HashMap<>();
     //根据订阅方法的名字保存的订阅者的Map
    final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
    final StringBuilder methodKeyBuilder = new StringBuilder(128);

    Class<?> subscriberClass;//订阅者的Class
    Class<?> clazz; //订阅者的Class
    boolean skipSuperClasses; 
    SubscriberInfo subscriberInfo;

    void initForSubscriber(Class<?> subscriberClass) {
        this.subscriberClass = clazz = subscriberClass;
        skipSuperClasses = false;
        subscriberInfo = null;
    }

。。。
}

可以看到这个FindState就是一个保存订阅者和订阅方法信息的实体类,包括了订阅类的订阅的所有事件类型和订阅方法。

好了再回到上面那里拿到findstate后,执行findUsingReflectionInSingleClass(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();
        //筛选拿到使用public公有修饰符修饰的
        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            //获取这个方法的参数类型
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 1) {
                //获取这个方法Subscribe.class类型的注解对象
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                if (subscribeAnnotation != null) {
                    //如果Subscribe.class类型的注解对象不为空则拿到它的第一个参数(其实就是发送的事件),然后把这个事件,线程模式,优先级,是否为粘性都保存到这个的findState.subscriberMethods中
                    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");
        }
    }
}

这个方法的作用就是拿到订阅者的所有方法的集合,遍历这个集合,判断这些方法是否满足用@Subscribe标注,并且方法的参数长度为1,并且为公开的。那么这个方法即为订阅方法。

至此,这个 findUsingReflection(subscriberClass)的作用基本理清了。

5、好了,上面的分析都是在获取这个订阅者的所有订阅方法。然后我们回到步骤二中,遍历这个订阅方法的集合,调用 subscribe(subscriber, subscriberMethod);

我们再看看里面做了什么?

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    //获取事件类型
    Class<?> eventType = subscriberMethod.eventType;
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    //通过subscriptionsByEventType(步骤一有说:根据事件类型保存所有的订阅信息)获取订阅信息Subscription的集合
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    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);
        }
    }

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

    //判断当前订阅方法是否为粘性,如果是立刻把事件post给订阅者
    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);
        }
    }
}

在此,EventBus的注册到处就完成了。我们在回头捋一遍:

先来回顾下这几个成员变量:

Subscription : 订阅信息实体类。 属性包括订阅者和订阅方法  

Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType: key为事件类型,value为订阅者集合。就是保存每个事件对应的订阅者的集合的Map。
Map<Object, List<Class<?>>> typesBySubscriber: key为订阅者,value为订阅事件。就是保存每个订阅者所对应的订阅方法集合。
Map<Class<?>, Object> stickyEvents: 粘性事件集合
  1. 首先拿到EventBus的实例,在注册方法中拿到订阅的对象,
  2. 再通过反射或者注解器拿到这个对象的所有订阅方法。遍历这个订阅方法集合。
  3. 把当前的订阅信息(订阅者和订阅方法)保存到subscriptionsByEventType 中
  4. 把当前的方法的订阅事件保存到typesBySubscriber,
  5. 还判断当前的订阅方法是否为粘性,如果是则post给订阅者。
  6. 循环c、d、e直接结束。

这里写图片描述

三、现在看下EventBus的发送事件的源码。

1、post事件

public void post(Object event) {
    //获取当前线程的postingState
    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状态
            postingState.isPosting = false;
            postingState.isMainThread = false;
        }
    }
}

在这里相信会对这个currentPostingState产生疑问,它是EventBus的 一个成员变量,但这个是什么东西呐,有什么作用呐?

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

ThreadLocal 叫线程局部变量。它的作用就是把当前线程的某些状态(如例子中的PostingState)保存起来,避免在多线程中其他线程对这些状态的影响。这里不做详细的解析,想更清楚的了解,ThreadLocal详解

所以这个步骤的作用是拿到当前线程保存的分发队列进行分发。

2、好了。回到1中开始分发的while循环,看到事件的分发是通过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) {
            logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
        }
        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                eventClass != SubscriberExceptionEvent.class) {
            post(new NoSubscriberEvent(this, event));
        }
    }
}

从上面的代码可以看到这里的作用找出当前事件的父类和接口,并且添加到一个集合中,循环这个集合开始分发。

这里有人会问为什么会触发父类和接口呐?

如果认真向下就会知道,加入A继承B,那么A是包括了B的。假如发出的事件时A,那么自然就触发了订阅B事件的响应函数。当然,是否触发父类和接口是可以设置的,这个需要通过EventBus的builder来设置。

3、好了,从2中看到方法会执行到postSingleEventForEventType(event, postingState, clazz) 这里。
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;
}

看到这里。是不是发现这个subscriptionsByEventType有点眼熟。没错,这个就是注册时保存的根据每种订阅事件类型保存的订阅者集合。拿到订阅该事件的订阅者集合,然后遍历进行事件分发。

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:
            if (mainThreadPoster != null) {
                mainThreadPoster.enqueue(subscription, event);
            } else {
                // temporary: technically not correct as poster not decoupled from subscriber
                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来进行切换,从代码中可以看到有mainThreadPoster,backgroundPoster,asyncPoster。mainThreadPoster是在订阅初始化时就创建的,而backgroundPoster,asyncPoster内部都通过EventBus的getExecutorService(),而获取到的就是 Executors.newCachedThreadPool()。这个是原生的四种线程池的其中一个。

4、从3可以看到接收到订阅事件的响应函数是在 invokeSubscriber(subscription, event)中执行的。
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);
    }
}

至此,EventBus的post到此完成。

好了,我们在来捋一下整个流程。
1. 通过ThreadLocal拿到当前线程保存的事件分发队列,并把当前事件添加到队列中;
1. 如果触发事件的父类和接口,则需要拿到它们并添加到一个事件集合中;
1. 遍历事件集合,然后通过subscriptionsByEventType拿到订阅该事件的订阅者集合,遍历该订阅者集合 在相应的线程中通过反射进行响应函数的调用执行。

这里写图片描述

四、再来看看解绑unRegister的源码。

public synchronized void unregister(Object subscriber) {
     //拿到当前订阅者的订阅事件集合
    List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
    if (subscribedTypes != null) {
        for (Class<?> eventType : subscribedTypes) {
              unsubscribeByEventType(subscriber, eventType);
        }
        // 把当前订阅者的订阅事件集合从总事件map中删除 
        typesBySubscriber.remove(subscriber);
    } else {
        logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
    }
}

上面拿到订阅者对于的订阅事件集合后,进行遍历,执行了 unsubscribeByEventType(subscriber, eventType)这个方法。

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

上面的代码都不难,都是把订阅者和订阅事件从保存的map中移除,避免了对这些将被销毁的对象的引用,防止造成内存泄漏。

五、最后,我们来总结一下整个流程:

订阅 register:
1. 在register订阅方法拿到订阅者,通过反射或者注解器拿到订阅者的所有订阅方法,进行遍历。
1. 拿到这方法的订阅信息,根据优先级插入到队列中,再把队列保存到以事件为key的map中。
1. 把当前订阅事件保存到 以订阅者为key的,订阅事件集合为value的map中。
1. 判断是否为粘性事件,是的话立刻把事件分发给订阅者。
1. 遍历是否完成,是即结束,否就重复步骤2。

发送事件 post:
1. 通过ThreadLocal拿到当前线程的发送队列。把事件添加到队列中;
1. 判断事件是否正在分发,是则结束,否则继续;
1. 遍历事件队列;
1. 判断是否触发父类和接口,是的话拿到该事件及它的继承链父类,接口的集合,然后进行遍历;
1. 从保存所有订阅信息的map拿到以当前事件类型为key的订阅信息(订阅者和订阅方法);
1. 根绝订阅方法指定的线程模式做线程切换,并通过反射执行订阅方法。
1. 判断两个循环是否结束,是则结束,否则继续。

取消订阅 unregister:

  1. 拿到当前订阅者的订阅事件集合,遍历;
  2. 从保存所有订阅信息的map中移除以该订阅事件为key的订阅信息集合;
  3. 循环是否结束。是则把当前当前订阅者的订阅事件集合从保存的map中移除。否则继续2步;
  4. 结束。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值