EventBus源码解读文档

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiey94/article/details/82904782

顺序前后有些乱,请见谅:

###EventBus源码解析

先看一个使用的例子:

public class MainActivity extends AppCompatActivity {

    private TextView tvShow;
    private Button btnShow;

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

        tvShow = findViewById(R.id.tv_show);
        btnShow = findViewById(R.id.btn_show);
        btnShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Random random = new Random();
                int num = random.nextInt();
                UserBean userBean = new UserBean("00001", "bb", "man");
                EventBus.getDefault().post(userBean);
            }
        });

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void event(UserBean info) {
        tvShow.setText(info.getName());
    }


    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }
}

简单使用也就比较简单:
先注册,然后定义订阅事件,解注册,发送事件

EventBus.getDefault().register(this);
EventBus.getDefault().post(userBean);
EventBus.getDefault().unregister(this);
@Subscribe(threadMode = ThreadMode.MAIN)
public void event(UserBean info) {
    tvShow.setText(info.getName());
}

从EventBus的入口进入

EventBus.getDefault().register(this);

首先看getDefault(),是一个double check的单例

static volatile EventBus defaultInstance;
public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}
public EventBus() {
    this(DEFAULT_BUILDER);
}
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
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;
}

EventBusBuilder

public class EventBusBuilder {
    //开辟一个线程池
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
    //log
    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;
    
    boolean eventInheritance = true;
    //注解
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    List<Class<?>> skipMethodVerificationForClasses;
    List<SubscriberInfoIndex> subscriberInfoIndexes;
    Logger logger;
    //主线程的支持类
    MainThreadSupport mainThreadSupport;

    EventBusBuilder() {
    }

    /** Default: true */
    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
        this.logSubscriberExceptions = logSubscriberExceptions;
        return this;
    }

    /** Default: true */
    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
        this.logNoSubscriberMessages = logNoSubscriberMessages;
        return this;
    }

    /** Default: true */
    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
        return this;
    }

    /** Default: true */
    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
        this.sendNoSubscriberEvent = sendNoSubscriberEvent;
        return this;
    }

    /**
     * Fails if an subscriber throws an exception (default: false).
     * <p/>
     * Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way, you won't miss
     * exceptions during development.
     */
    public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
        this.throwSubscriberException = throwSubscriberException;
        return this;
    }

    /**
     * By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified).
     * Switching this feature off will improve posting of events. For simple event classes extending Object directly,
     * we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be
     * >20%.
     * <p/>
     * However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app,
     * unless it is posting at high rates, e.g. hundreds/thousands of events per second.
     */
    public EventBusBuilder eventInheritance(boolean eventInheritance) {
        this.eventInheritance = eventInheritance;
        return this;
    }


    /**
     * Provide a custom thread pool to EventBus used for async and background event delivery. This is an advanced
     * setting to that can break things: ensure the given ExecutorService won't get stuck to avoid undefined behavior.
     */
    public EventBusBuilder executorService(ExecutorService executorService) {
        this.executorService = executorService;
        return this;
    }

    /**
     * Method name verification is done for methods starting with onEvent to avoid typos; using this method you can
     * exclude subscriber classes from this check. Also disables checks for method modifiers (public, not static nor
     * abstract).
     */
    public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
        if (skipMethodVerificationForClasses == null) {
            skipMethodVerificationForClasses = new ArrayList<>();
        }
        skipMethodVerificationForClasses.add(clazz);
        return this;
    }

    /** Forces the use of reflection even if there's a generated index (default: false). */
    public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
        return this;
    }

    /** Enables strict method verification (default: false). */
    public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
        this.strictMethodVerification = strictMethodVerification;
        return this;
    }

    /** Adds an index generated by EventBus' annotation preprocessor. */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if (subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

    /**
     * Set a specific log handler for all EventBus logging.
     * <p/>
     * By default all logging is via {@link android.util.Log} but if you want to use EventBus
     * outside the Android environment then you will need to provide another log target.
     */
    public EventBusBuilder logger(Logger logger) {
        this.logger = logger;
        return this;
    }

    Logger getLogger() {
        if (logger != null) {
            return logger;
        } else {
            // also check main looper to see if we have "good" Android classes (not Stubs etc.)
            return Logger.AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null
                    ? new Logger.AndroidLogger("EventBus") :
                    new Logger.SystemOutLogger();
        }
    }

    //不为空则直接返回,为空则判断日志的可使用状态,可使用则获取当前主线程的Looper,将Looper传入到MainThreadSupport的实现类AndroidHandlerMainThreadSupport中
    MainThreadSupport getMainThreadSupport() {
        if (mainThreadSupport != null) {
            return mainThreadSupport;
        } else if (Logger.AndroidLogger.isAndroidLogAvailable()) {
            Object looperOrNull = getAndroidMainLooperOrNull();
            return looperOrNull == null ? null :
                    new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
        } else {
            return null;
        }
    }

    Object getAndroidMainLooperOrNull() {
        try {
            return Looper.getMainLooper();
        } catch (RuntimeException e) {
            // Not really a functional Android (e.g. "Stub!" maven dependencies)
            return null;
        }
    }

    /**
     * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be
     * done only once before the first usage of the default EventBus.
     *
     * @throws EventBusException if there's already a default EventBus instance in place
     */
    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;
        }
    }

    /** Builds an EventBus based on the current configuration. */
    public EventBus build() {
        return new EventBus(this);
    }

}

然后看register

public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

register的参数是Object,(这意思就是能注册的多了去了,这里我就拿MainActivity说事了)

Class<?> subscriberClass = subscriber.getClass();

获取当前的Class,(这里也就是com.xiey94.eventbusstudy.MainActivity的Class)

List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);

这里涉及到了三个东西
SubscriberMethod:订阅方法的包装类
subscriberMethodFinder:(private final SubscriberMethodFinder subscriberMethodFinder;):unknow
findSubscriberMethods:根据方法名可以看出是寻找订阅方法的;

SubscriberMethod

/** Used internally by EventBus and generated subscriber indexes. */
public class SubscriberMethod {
    //订阅的方法
    final Method method;
    //将要运行的线程
    final ThreadMode threadMode;
    //参数类型(这里也就是com.xiey94.eventbusstudy.UserBean)
    final Class<?> eventType;
    //优先级
    final int priority;
    //是否为粘性事件(例:A跳转到C,按照启动流程,先启动A,A注册了,然后在A中post通知,在C中定义订阅方法,但是这时A还没启动(跳转)到C,也就是说C还没有onCreate,也就还没register,所以也就接收不到这个订阅事件了;这是普通事件,有了粘性事件就不一样了,哪怕你还没有注册,只要有post的,那当你register之后还是会接收到这个post的通知)
    final boolean sticky;
    /** Used for efficient comparison */
    //用于拼接,然后对比比较
    String methodString;

    //构造
    public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
        this.method = method;
        this.threadMode = threadMode;
        this.eventType = eventType;
        this.priority = priority;
        this.sticky = sticky;
    }

    //覆写,比较他们的拼接是否相同(当前:MainActivity#event(com.xiey94.eventbusstudy.UserBean)
    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        } else if (other instanceof SubscriberMethod) {
            checkMethodString();
            SubscriberMethod otherSubscriberMethod = (SubscriberMethod)other;
            otherSubscriberMethod.checkMethodString();
            // Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6
            return methodString.equals(otherSubscriberMethod.methodString);
        } else {
            return false;
        }
    }

    private synchronized void checkMethodString() {
        if (methodString == null) {
            // Method.toString has more overhead, just take relevant parts of the method
            StringBuilder builder = new StringBuilder(64);
            builder.append(method.getDeclaringClass().getName());
            builder.append('#').append(method.getName());
            builder.append('(').append(eventType.getName());
            methodString = builder.toString();
        }
    }

    @Override
    public int hashCode() {
        return method.hashCode();
    }
}

整体还是没有难理解的地方

SubscriberMethodFinder
暂时只涉及到这个类的一个方法,所以先放放

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    /*METHOD_CACHE:private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
    *这个是缓存整个App所有的订阅方法,以Class为key,将当前Class中所有的订阅方法都分别包装为SubscriberMethod,然后放到List中;(当前就是MainActivity为key,List中目前就一个订阅方法,就是event)
    *这里根据当前传进来的Class,也就是MainActivity的class,来查找所有订阅方法,如果找到的就返回所有的订阅方法
    不存在的情况暂时先不分析
    **/
    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;
    }
}

再回到register方法中:

public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

加个一个同步锁,然后开始针对当前的订阅者找到所有的订阅方法,开始订阅
subscribe:

// Must be called in synchronized block:必须在同步锁中调用
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    //获取当前参数类型,也就是UserBean
    Class<?> eventType = subscriberMethod.eventType;
    //将传来的class和方法进行包装
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    //对参数类型进行判断,如果没有这个参数类型则添加到list中,如果当前参数类型已经有了,就不可以再注册这个方法,会抛异常;如果已经有event(UserBean userBean)方法了,就不能再定义一个同参数类型的event2(UserBean userBean)方法了,不然发通知的时候,就不知道当前Class中那个事件去响应了
    //subscriptionsByEventType:Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;针对整个App的,以参数类型为key,将不同Class中的该参数类型的订阅方法结合所属的Class包装成Subscription作为集合作为value;
    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;
        }
    }
    
    //Map<Object, List<Class<?>>> typesBySubscriber;以Class为Key,然后将该Class中的订阅方法的所有参数类型放到list中
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    subscribedEvents.add(eventType);
    
    //判断该订阅方法是否为粘性事件,如果是的话则
    if (subscriberMethod.sticky) {
        //是否可继承,相当于super,父类的订阅事件子类也会先执行一下,默认true
        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();
                //去所有的粘性事件中查找所有的参数类型,判断当前参数类型是否是某个订阅事件同一类型或者是它的父类,如果是,则取出粘性事件;这里也就是说,如果在整个App中,如果有订阅事件的参数为当前参数类型的子类,则触发所有参数为该子类的订阅事件
                if (eventType.isAssignableFrom(candidateEventType)) {
                    Object stickyEvent = entry.getValue();
                    //触发事件
                    checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                }
            }
        } else {
            //private final Map<Class<?>, Object> stickyEvents;以参数类型作为Key,粘性事件参数作Value,根据当前订阅方法的参数类型,取出粘性事件
            Object stickyEvent = stickyEvents.get(eventType);
            //触发事件,参数为包装了的Subscription(Class+方法)、粘性事件
            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
        }
    }
}
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
    if (stickyEvent != null) {
        // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
        // --> Strange corner case, which we don't take care of here.
        //判断该粘性事件是否为空,不为空则触发,参数多了一个判断主线程(UI线程)
        postToSubscription(newSubscription, stickyEvent, isMainThread());
    }
}
private boolean isMainThread() {
    //当为空时为主线程,否则看mainThreadSupport.isMainThread()
    return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true;
}

public interface MainThreadSupport {
    //判断主线程
    boolean isMainThread();
    
    //构建发射器
    Poster createPoster(EventBus eventBus);

    class AndroidHandlerMainThreadSupport implements MainThreadSupport {

        private final Looper looper;

        public AndroidHandlerMainThreadSupport(Looper looper) {
            this.looper = looper;
        }

        @Override
        public boolean isMainThread() {
            return looper == Looper.myLooper();
        }

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

}

HandlerPoster

public class HandlerPoster extends Handler implements Poster {
    //发射中队列
    private final PendingPostQueue queue;
    //最长等待注册时长;当10秒后没有注册成功,则去掉重新开始,防止阻塞主线程
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    //处理激活
    private boolean handlerActive;

    protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

    @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;检查两次,如果两次都是null,则说明没有,直接返回
                        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;
        }
    }
}
    void invokeSubscriber(PendingPost pendingPost) {
        //取出包装方法类,和参数
        Object event = pendingPost.event;
        Subscription subscription = pendingPost.subscription;
        //处理PendingPost,里面的值清空;如果发射池小于10000,则重新添加进去,免了创建新对象的开销
        PendingPost.releasePendingPost(pendingPost);
        
        if (subscription.active) {
            invokeSubscriber(subscription, event);
        }
    }

发送器接口

interface Poster {

    /**
     * Enqueue an event to be posted for a particular subscription.
     *
     * @param subscription Subscription which will receive the event.
     * @param event        Event that will be posted to subscribers.
     * 参数为包装类(Class+event),
     */
    void enqueue(Subscription subscription, Object event);
}

Subscription

final class Subscription {
    //参数类型
    final Object subscriber;
    //包装后的方法
    final SubscriberMethod subscriberMethod;
    /**
     * Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery:当unregister被调用时,active=false,当队列分发时被调用
     * {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
     */
    volatile boolean active;

    Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
        this.subscriber = subscriber;
        this.subscriberMethod = subscriberMethod;
        active = true;
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Subscription) {
            Subscription otherSubscription = (Subscription) other;
            return subscriber == otherSubscription.subscriber
                    && subscriberMethod.equals(otherSubscription.subscriberMethod);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
    }
}

回到发射事件那边

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

这里我们是Main

case MAIN:
    if (isMainThread) {
        invokeSubscriber(subscription, event);
    } else {
        mainThreadPoster.enqueue(subscription, event);
    }
break;

如果是主线程,则invokeSubscriber;否则就是发射器异步发射粘性事件

    void invokeSubscriber(Subscription subscription, Object event) {
        try {
            //method为订阅方法,subscription.subscriber为实例对象,event为Subscription中的粘性事件参数
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }

如果在主线程,则反射执行粘性事件,否则异步执行

    public void enqueue(Subscription subscription, Object event) {
        //构建一个发射包装器
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
        
            queue.enqueue(pendingPost);
            //将handlerActive状态更换
            if (!handlerActive) {
                handlerActive = true;
                //
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

PendingPost

final class PendingPost {
    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();

    Object event;
    Subscription subscription;
    PendingPost next;

    private PendingPost(Object event, Subscription subscription) {
        this.event = event;
        this.subscription = subscription;
    }
    
    //传进来类包装方法,和方法参数类型
    static PendingPost obtainPendingPost(Subscription subscription, Object event) {
        synchronized (pendingPostPool) {
            //拿取最后加入的发射器,将包装方法和参数包装成一个发射器并返回
            int size = pendingPostPool.size();
            if (size > 0) {
                PendingPost pendingPost = pendingPostPool.remove(size - 1);
                pendingPost.event = event;
                pendingPost.subscription = subscription;
                pendingPost.next = null;
                return pendingPost;
            }
        }
        return new PendingPost(event, subscription);
    }

    //释放用过的发射器,清空内容,重回发射池
    static void releasePendingPost(PendingPost pendingPost) {
        pendingPost.event = null;
        pendingPost.subscription = null;
        pendingPost.next = null;
        synchronized (pendingPostPool) {
            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
    }

}

PendingPostQueue

//构建一个发射器队列
final class PendingPostQueue {
    private PendingPost head;
    private PendingPost tail;

    synchronized void enqueue(PendingPost pendingPost) {
        if (pendingPost == null) {
            throw new NullPointerException("null cannot be enqueued");
        }
        if (tail != null) {
            tail.next = pendingPost;
            tail = pendingPost;
        } else if (head == null) {
            head = tail = pendingPost;
        } else {
            throw new IllegalStateException("Head present, but no tail");
        }
        //唤醒线程,随时抢占时间片
        notifyAll();
    }

    synchronized PendingPost poll() {
        PendingPost pendingPost = head;
        if (head != null) {
            head = head.next;
            if (head == null) {
                tail = null;
            }
        }
        return pendingPost;
    }

    synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
        if (head == null) {
            wait(maxMillisToWait);
        }
        return poll();
    }

}

回溯一下:
1、首先从register进去,然后将当前Class中的订阅方法包装成一个SubscriberMethod;
2、将Class作为Key,Class所属的订阅方法都放到一个List中作为Value,放到了SubscriberMethodFinder中的METHOD_CACHE(Map<Class<?>, List>)中;
3、然后开始订阅所有的订阅事件,在订阅事件方法中,有包装了一个东西,将Class和SubscriberMethod包装成了Subscription;
4、又构建了一个Map,以参数类型作为Key,将所有Class中属于该参数类型的订阅方法放到一个List中subscriptionsByEventType(Map<Class<?>, CopyOnWriteArrayList>);
5、将传进来的订阅事件按照优先级排序添加进来;
6、又构建了一个Map(Map<Object, List<Class<?>>> typesBySubscriber),将Class作为Key,将当前Class中订阅方法的所有参数添加到List中作为Value;
7、按照道理讲,如果暂时不管粘性事件,则register就结束了;但是有了粘性事件就不一样了,当你register好了之后,跟随而来的粘性事件就要响应;
8、构建了一个stickyEvents(Map<Class<?>, Object> stickyEvents;)用参数类型作为Key,用参数值作为Value,
9、如果eventInheritance==true,也就是如果该粘性事件的类型参数有子类也作为某个订阅方法的参数,则子类订阅方法也响应该通知;
10、判断当前订阅事件指定的线程,也就是threadMode,如果是MAIN,判断当前是否是主线程,如果是则将stickEvents中的传进来对应的参数数据进行反射执行订阅方法;如果不是主线程,则在Handler中构建PendingPost发射器(从PendingPostQueue中获取,并包装对应参数),唤醒线程,抢占时间片,然后发送异步消息,因为HandlerPoster是在主线程中创建的,所以响应是在主线程;

现在到post方法:

    public void post(Object event) {
        //获取post线程的状态值
        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;
            }
        }
    }
//做了一个线程并发变量保存处理
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
    @Override
    protected PostingThreadState initialValue() {
        return new PostingThreadState();
    }
};
/** For ThreadLocal, much faster to set (and get multiple values). */
//可以快速设置值
final static class PostingThreadState {
        final List<Object> eventQueue = new ArrayList<>();
        boolean isPosting;
        boolean isMainThread;
        Subscription subscription;
        Object event;
        boolean canceled;
    }
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);
                //针对所有的类型都进行事件处理,只要有事件发射就会返回true
                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进来的时候,设置了isPosting进行拦截,所以这里再调用的时候,具体的内容就执行不了了,这个方法就结束了,最终将isPosting撤销拦截;但是这里有个问题,因为这里调用post的时候,状态中的参数队列又增加了一个,这时while里的循环就又有了一个执行事件,然后再一次这样,当再次到达post之前时,有一个判断条件eventClass != NoSubscriberEvent.class,这个时候就可以跳出循环了;
                post(new NoSubscriberEvent(this, event));
            }
        }
    }
/** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */
//查找所有该参数类型的事件
    private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
        synchronized (eventTypesCache) {
            //以该参数作为依据,添加自己,添加该参数所实现的接口,还有接口的父接口,都添加进去,还有该参数的父类
            List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
            if (eventTypes == null) {
                eventTypes = new ArrayList<>();
                Class<?> clazz = eventClass;
                while (clazz != null) {
                    //添加自己
                    eventTypes.add(clazz);
                    //添加所有接口
                    addInterfaces(eventTypes, clazz.getInterfaces());
                    //找到自己的父类,再来找父类自己以及父类的接口,循环
                    clazz = clazz.getSuperclass();
                }
                //将所有的类型都放到eventTypesCache中,参数类型作为Key
                eventTypesCache.put(eventClass, eventTypes);
            }
            return eventTypes;
        }
    }
/** Recurses through super interfaces. */
//将所有接口以及父接口都添加进来
    static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
        for (Class<?> interfaceClass : interfaces) {
            if (!eventTypes.contains(interfaceClass)) {
                eventTypes.add(interfaceClass);
                addInterfaces(eventTypes, interfaceClass.getInterfaces());
            }
        }
    }
//以参数类型作为key,该参数类型的父类,接口,父父类,父父接口等等一直往上接口的List作为Value
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
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;
                }
                //如果发射事件终止,则停止for循环,直接返回true
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }

回溯一下:
1、发送一个事件;为了防止线程间错乱,使用了线程本地变量ThreadLocal来管理当前线程中所需要的参数,并将这些参数包装为一个状态类PostingThreadState;
2、将事件参数加入到状态参数的队列中;
3、用isPosting来拦截入口;
4、赋值到状态中;
5、如果状态为取消,则发射终止并抛出异常;
6、对状态中的参数队列进行循环操作;并发射
7、如果参数继承关系是开启状态则遍历参数的所有接口类型以及继承的父类型,依次往上获取所有类型,然后开始循环发送事件;
8、如果该参数类型的订阅事件存在则直接发射执行;后续同之前的粘性事件相同,判断是否是在主线程中,或者子线程中,最终反射执行订阅方法;
9、如果该参数类型的订阅事件不存在,则再次发送一个空参数事件,然后被自己的isPosting拦截在执行外面,但是状态的参数队列将空参数事件加入到了队列,又发射事件,辗转又到了post,但是这次会判断该参数事件是否是空事件来判断是否终止,最终终止,释放isPosting拦截;
10、如果继承关系关闭则只执行当前参数的订阅事件。

最后就到了解注册unregister

/** Unregisters the given subscriber from all event classes. */
    public synchronized void unregister(Object subscriber) {
        //获取当前Class中的所有订阅事件的参数类型
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            //解注册完所有的订阅事件,然后从map中移除该Class
            typesBySubscriber.remove(subscriber);
        } else {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }
    /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
    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) {
                    //active=false宣告解注册,并且移除类包装方法
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

已经解注册了,再来单独说一下黏性事件sticky
有如下几个方法:

黏性事件 作用
postSticky 发送黏性事件,将之记录到stickyEvents中,然后发送post事件,但是找不到订阅Class,所以无用,只能等订阅Class订阅了才能跟随过去
getStickyEvent 获取参数类型的值,如果参数类型没有实例化或者类型不对则抛出异常
removeStickyEvent 根据参数类型从stickyEvents中移除,并返回该参数类型的对象,同上,没有实例化或者类型不对则抛出异常
removeStickyEvent 根据某类型对象找到该类型,然后判断移除,并返回成功失败操作(Boolean)
removeAllStickyEvents 清空stickyEvents;

参考:
EventBus3.0源码解读


猜你喜欢

转载自blog.csdn.net/xiey94/article/details/82904782