3

EventBus使用和解析

 3 years ago
source link: https://blog.csdn.net/mingyunxiaohai/article/details/86303114
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

EventBus是Android上的订阅事件总线,它简化了各组件间组件和后台之间的通信,使用订阅者和发布者模式进行解耦,使用方便。

使用EventBus的好处:

1)简化了组件之间的通信
2)将事件发送者和接收者分离
3)在UI之间(Activity,Fragment),后台线程中表现良好
4)避免复杂并且容易出错的依赖关系和生命周期问题。
5)很快,专门针对高性能进行了优化
6)很小jar包<50k
7)具有交付线程,用户优先级等高级功能

EventBus 特色

1)方便的基于注解的API,只需将@Subscribe注解放到订阅者方法上即可。EventBus不需要在应用程序的运行时进行注释反射。
2)当和UI交互的时候,无论实践如何发布,EventBus都可以在主线程中传递事件
3)如果订阅者长时间运行任务,EventBus也可以使用后台线程来避免线程阻塞
4)如果事件A是事件B的父类,那么事件B的已发布事件也将发给订阅了A的订阅者

第一步:gradle中添加依赖

implementation 'org.greenrobot:eventbus:3.1.1'

第二步:定义事件

public class MessageEvent {

    public final String message;

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

第三步:准备订阅者
方法名字自己可以随便定义,只要方法上面加@Subscribe注解就行

// 当MessageEvent消息发布的时候,该方法可以收到消息,在UI线程中显示toast
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
 
// 当SomeOtherEvent事件发布的时候该方法可以收到消息
@Subscribe
public void handleSomethingElse(SomeOtherEvent event) {
    doSomethingWith(event);
}

第四步:订阅者需要在事件总线中注册和注销,只有注册了才能收到事件

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

不一定非得在onStart()和onStop()中,根据自己的需要,可以在onCreate()中和onDestory()中。
第五步:发布事件

EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

发从黏性事件:

跟系统的黏性广播类似,就是在发送事件之后再订阅该事件,也能收到该事件

EventBus.getDefault().postSticky(new MyEvent());

在EventBus中可以使用下面几种线程模型来定义将调用事件处理方法的线程

POSTING(默认):
发布事件和订阅事件在同一个线程中,事件传递是同步完成的,一旦发布完成,所有的订阅者都将被调用,这种线程模型开销最小,因为它完全避免了线程切换,因此完成简单任务推荐使用这种模式。避免在此模式下执行耗时操作,因为它会阻塞事件的传递,甚至引起ANR。

MAIN :
事件处理将在Android的主线程中进行,使用此模式必须快速返回避免阻塞主线程。

MAIN_ORDERED:
订阅者将在Android主线程中调用,该事件总是排队等待以后交付给订阅者,因此对post的调用将立即返回,为事件处理提供了更严格一直的顺序。

BACKGROUND:
如果事件是在主线程中发布,则另起一个线程来处理事件,如果发布线程不是主线程,则在发布线程中调用。这个事件处理函数中禁止更新UI

ASYNC:
无论事件在哪个线程中发布,该函数都会重新建立一个线程来处理事件。

EventBus源码解析

当我们使用EventBus的时使用EventBus.getDefault()来获取EventBus的实例那就从它来开始

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

可以看到这一个双重校验的单例模式创建了EventBus的实例。然后看看其构造方法:

 public EventBus() {
        this(DEFAULT_BUILDER);
    }
    
//这里的DEFAULT_BUILDER是一个Builder的成员变量,用来构造EventBus
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();

this调用了其一个参数的构造方法

    EventBus(EventBusBuilder builder) {
        logger = builder.getLogger();
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        mainThreadSupport = builder.getMainThreadSupport();
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                builder.strictMethodVerification, builder.ignoreGeneratedIndex);
        logSubscriberExceptions = builder.logSubscriberExceptions;
        logNoSubscriberMessages = builder.logNoSubscriberMessages;
        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        throwSubscriberException = builder.throwSubscriberException;
        eventInheritance = builder.eventInheritance;
        executorService = builder.executorService;
    }

可以看到构造方法中初始化了很多Map:subscriptionsByEventType,typesBySubscriber,stickyEvents 来保存订阅的方法,订阅者监听的事件类型,黏性事件。

还有几个Poster:mainThreadPoster,backgroundPoster,asyncPoster

这几个Poster是啥呢?他们都实现了Poster接口,Poster接口里面有个入队的方法。

interface Poster {
    void enqueue(Subscription subscription, Object event);
}

mainThreadPoster:

mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;

...

    public Poster createPoster(EventBus eventBus) {
            return new HandlerPoster(eventBus, looper, 10);
        }

...

public class HandlerPoster extends Handler implements Poster {}

可以看到mainThreadPoster是一个Handler。

backgroundPoster:

 class BackgroundPoster implements Runnable, Poster {}

可以看到backgroundPoster是一个Runnable

asyncPoster:

AsyncPoster implements Runnable, Poster {}

asyncPoster也是一个Runnable

我们知道Handler,Runnable都是负责线程调度的嘛,其实对应的就是上面说的那几种模式,OK先知道这几个然后往下看,EventBus其实就是一个订阅者消费者模式,那就从注册订阅者开始

  public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        //通过findSubscriberMethods方法找到subscriber类中的订阅的方法
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

从上面的代码可以看到通过SubscriberMethodFinder的findSubscriberMethods方法找到subscriber类中的订阅的方法,SubscriberMethodFinder在构造方法中初始化好的 ,然后遍历找到的这些方法,通过subscribe方法完成订阅,先看看怎么找的

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
       //先从缓存中找,如果有就直接返回
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }
        //是否忽略注解生成器
        if (ignoreGeneratedIndex) {
        //通过反射获取subscriberMethods
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            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;
        }
    }

先从缓存中取,如果有直接返回,如果没有判断是否忽略注解生成器ignoreGeneratedIndex如果是采用反射回去方法,如果不是用另一个方法。ignoreGeneratedIndex默认是false,所以我们通常使用的是findUsingInfo这个方法来获取订阅的方法

    private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
    //准备一个FindState
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
        //获取订阅者信息,没有配置MyEventBusIndex返回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();
        }
        return getMethodsAndRelease(findState);
    }

先看一下FindState

static class FindState {
        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
        final Map<Class, Object> anyMethodByEventType = new HashMap<>();
        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;
        }
        
        ......

可以看大FindState就是一个包装 类,里面有各种list和各种Map来保存订阅方法,订阅类

回到findUsingInfo方法继续往下,通过getSubscriberInfo方法来获取订阅者信息,因为我们前面使用的是忽略注解生成器,所以会返回null,然后进入findUsingReflectionInSingleClass方法

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();
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    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()));
                        }
                    }
                } 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注解的方法也就是订阅的方法,和这个方法的相关信息,封装成SubscriberMethod对象最后保存到findState中的subscriberMethods这个list中。

最后调用getMethodsAndRelease方法并返回

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

这个方法就是把FindState存到缓存池里,然后返回订阅方法的信息。

OK到这里就返回了这个类中的所有订阅方法的信息的集合,也就是加了@Subscribe注解的方法的信息,然后可以在回到register注册方法中继续往下了,下面就是遍历这些方法进行订阅了,看看怎么订阅的呢

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);
        }
        subscribedEvents.add(eventType);

        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中,CopyOnWriteArrayList是一个线程安全的list

保存到subscriptionsByEventType这个map中,以参数类型为key,方法信息为value

然后进行优先级的判断优先级越高,会插到在当前List靠前面的位置;

通过订阅者获取该订阅者所订阅事件的集合,如果获取不到就创建一个放入Map typesBySubscriber中。
将当前的订阅事件添加到subscribedEvents中

最后判断是不是黏性事件,黏性事件最后都会调用checkPostStickyEventToSubscription方法。

总结:这里面做了两件事,第一件,把订阅方法和订阅者放到subscriptionsByEventType和typesBySubscriber这两个Map中保存。subscriptionsByEventType就是当发送事件的时候根据EventType找打订阅事件然后去处理。typesBySubscriber是在调用unregister(this)的时候,根据订阅者找到EventType,在根据EventType找到订阅事件进行解绑。第二件事就是如果是黏性事件,就立马执行。

到这里注册就告一段落啦,下面看看事件的发送

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

currentPostingThreadState是一个ThreadLocal类里面存储的是PostingThreadState里面保存了事件队列和线程状态的信息。ThreadLocal我们知道它是一个线程安全的对象封装,相当于一个线程中的局部变量。

获取事件队列,并把事件放进队列中

最后从队列中取出事件调用postSingleEvent来处理事件

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

首先取出事件类的类型
eventInheritance表示是否向上查找事件的父类,默认为true
通过lookupAllEventTypes找到所有Event和其父类事件并存在List中
通过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;
    }

从subscriptionsByEventType中取出对应的subscriptions(订阅方法信息)。

把这个Event和取出的subscriptions封装到PostingThreadState中

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

这里看到了熟悉的,刚开始使用的时候接触到的集中线程模式。那这里就是根据这几种线程模式来分别处理事件。

**POSTING:**调用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);
        }
    }

其实就是执行一开始通过反射得到的订阅方法,把事件传过去。

**MAIN:**如果是主线程,就直接执行反射方法,反之则使用mainThreadPoster的入队方法入队到把事件和订阅方法封装到PendingPost中然后放到PendingPostQueue这个链表中。PendingPost顾名思义就是将要执行的post,一开始的构造方法中我们知道mainThreadPoster其实就是个Handler,所以具体执行方法就在其handleMessage中执行

  @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            while (true) {
                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);
                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;
        }
    }

其实就是把刚才放到队列中的PendingPost取出来,去执行反射方法

MAIN_ORDERED: 在主线程中有序的执行

可以看到这里跟MAIN的区别是这里不是先判断是不是主线程,而是先判断mainThreadPoster是不是null,如果不是null就直接入队。我们知道mainThreadPoster在构造方法中就初始化好了,所以不为null。所以不管是在哪个线程,都一律去handler中去排队执行。

BACKGROUND:

如果不是主线程,就直接执行invokeSubscriber,执行反射中的方法;如果是主线程就使用backgroundPoster的入队方法入队到把事件和订阅方法封装到PendingPost中然后放到PendingPostQueue这个链表中。backgroundPoster我们在最开始的构造方法中知道他是一个Runnable,所以其具体执行方法就在其run方法中

 @Override
    public void run() {
        try {
            try {
                while (true) {
                    PendingPost pendingPost = queue.poll(1000);
                    if (pendingPost == null) {
                        synchronized (this) {
                            // Check again, this time in synchronized
                            pendingPost = queue.poll();
                            if (pendingPost == null) {
                                executorRunning = false;
                                return;
                            }
                        }
                    }
                    eventBus.invokeSubscriber(pendingPost);
                }
            } catch (InterruptedException e) {
                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

把刚才放到队列中的PendingPost取出来,去执行反射方法

ASYNC: 直接调用asyncPoster的入队方法,asyncPoster也是一个Runnable,所以其具体执行方法就在其run方法中

  @Override
    public void run() {
        PendingPost pendingPost = queue.poll();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        eventBus.invokeSubscriber(pendingPost);
    }

把刚才放到队列中的PendingPost取出来,去执行反射方法

BACKGROUND和ASYNC都是一个Runnable,但是我们可以看到他们的run方法和入队的方法中的实现并不一样,BACKGROUND中有个executorRunning,判断当前是不是又正在执行的。所以BACKGROUND是一个一个执行的,ASYNC是同事异步执行的。

最后是取消订阅

  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 {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

就是把存到subscriptionsByEventType和typesBySubscriber中的订阅方法和这个类对象移除。

总结:
当我们注册的时候,把要注册的类保存到typesBySubscriber这个Map中,把这个类中的订阅方法和订阅方法的各种参数信息保存到subscriptionsByEventType这个Map中,key是事件的类型。当发送事件的时候,根据事件的类型,从subscriptionsByEventType中找到对应的订阅方法,然后执行这些方法。取消注册的时候,把存到subscriptionsByEventType和typesBySubscriber中的订阅方法和这个类对象移除。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK