天天看点

阅读EventBus源码(笔记)待续1.EventBus.getDefault().register(this);2.EventBus.getDefault().unregister(this)参考

对源码的阅读不多,从用的比较多的EventBus开始,还是有些看不懂的地方。

最常用的写法:

EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);
EventBus.getDefault().post("hello");

    @Subscribe
    public void mainEvent(MessageEvent messageEvent) {
        if(messageEvent.getmStrMessage().equals(CommonEventMessage.LOGINED)) {
            mIMainView.updateMessage();
        }
      }
           

1.EventBus.getDefault().register(this);

1.1 getDefault():

/** Convenience singleton for apps using a process-wide EventBus instance. */
    public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }
           

这里就是一个单例的模式:首先直接做null的判断操作,如果为null了才去进行同步锁的操作,保证了性能。

接下来是加入了同步锁,防止多线程的干扰,但在

defaultInstance = new EventBus();
           

这里会产生一个问题,就是重排序的问题,当前这个已经进入的线程在进行实例化的时候,会发生三件事:

  1. 给 instance 分配内存
  2. 调用 Singleton 的构造函数来初始化成员变量
  3. 将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)

但是由于指令重排序,2和3的步骤可能发生颠倒,所以要对defaultInstance添加volatile关键字来避免这种情况:

static volatile EventBus defaultInstance;
           

1.2 register()

/**
     * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
     * are no longer interested in receiving events.
     * <p/>
     * Subscribers have event handling methods that must be annotated by {@link Subscribe}.
     * The {@link Subscribe} annotation also allows configuration like {@link
     * ThreadMode} and priority.
     */
    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }
           
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            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;
        }
    }
           

利用反射去查找当前类是否有接收订阅的方法,如果没有的话,则会抛出一个错误异常出来。然后把查找出来的方法进行一次遍历,然后添加订阅。

2.EventBus.getDefault().unregister(this)

/** Unregisters the given subscriber from all event classes. */
    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());
        }
    }
           

参考

如何正确地写出单例模式

秒懂,Java 注解 (Annotation)你可以这样学

深入浅出反射