EventBus源碼詳細分析-手寫EventBus核心代碼

本文由風聽雨聲授權原創發佈

EventBus 是一個面向Android和Java的開源庫,使用發佈者/訂閱者模式實現鬆散耦合,簡化組件之間的通信。使用簡單,效率高,體積小。具備高級特性,如傳遞線程、訂閱優先級等,下面是官方的EventBus原理圖

EventBus原理圖.png

本文將對EventBus(基於當前EventBus最新版本3.2.0)進行詳細的源碼分析,會有比較詳細的代碼註釋,本文將從以下方面進行展開

  • 基本使用簡單介紹

  • Subscribe註解

  • 註冊和訂閱事件

  • 取消註冊

  • 發送事件

  • 處理事件

  • 粘性事件

  • Annotation的使用方式

  • 手寫核心代碼

基本使用

註冊

EventBus.getDefault().register(this);

取消註冊

EventBus.getDefault().unregister(this);

發送事件

EventBus.getDefault().post("event");

接收事件

@Subscribe(threadMode = ThreadMode.MAIN)public void subscribeMethod(String event){
}

Subscribe註解

@Documented@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.POSTING;


    boolean sticky() default false;
    
    int priority() default 0;
}

運行時作用於方法的註解,註解的value有以下3個

  • 1.threadMode():接收事件的線程,默認POSTING,和發送事件同一線程

  • 2.sticky():是否爲粘性事件,默認false

  • 3.priority():接收事件優先級,默認0,即默認所有事件相同優先級

ThreadMode接收事件的線程

public enum ThreadMode {    POSTING,
    MAIN,
    MAIN_ORDERED,
    BACKGROUND,
    ASYNC
}

ThreadMode有以下5種

  • 1.POSTING:將在發佈事件的同一線程中直接調用訂閱者。這是默認設置。事件交付意味着開銷最少,因爲它完全避免了線程切換。

  • 2.MAIN:*在Android上,訂閱者將在Android的主線程(UI線程)中被調用。如果發佈線程是主線程、訂閱方方法將被直接調用,阻塞發佈線程。

  • 3.MAIN_ORDERED:在Android上,訂閱者將在Android的主線程(UI線程)中被調用。與MAIN不同的是事件將一直排隊等待交付。這確保了post調用是非阻塞的。

  • 4.BACKGROUND:在Android上,訂閱者將在後臺線程中被調用。如果發佈線程不是主線程,訂閱方方法將在發佈線程中直接調用。如果發佈線程是主線程,則EventBus使用後臺線程,它將按順序交付所有事件。

  • 5.ASYNC:訂閱將在一個單獨的線程中被調用。總是獨立於發佈線程和主線程。

註冊和訂閱事件

getDefault(),雙重判斷加鎖的單例

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

Builder設計模式,傳入默認Builder

     

  public EventBus() {        this(DEFAULT_BUILDER);
    }


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

默認Builder參數初始值

       

public class EventBusBuilder {    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();


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

註冊

  1. 獲取訂閱的class對象

   2.根據訂閱的class對象,解析訂閱方法Subscribe註解,並封裝成SubscriberMethod,加入到
List<SubscriberMethod>集合

  1. 處理事件

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

findSubscriberMethods(Class<?> subscriberClass)

           1.從緩存中取,有直接返回

  1. findUsingInfo(subscriberClass)和findUsingReflection(subscriberClass),兩者都是通過反射解析Subscribe,findUsingInfo比findUsingReflection多了FindState的對象池

    3.subscriberMethods加入緩存,以便第二次打開不再需要反射解析

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {        //先從緩存的Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE ,key爲註冊的class對象,value爲List<SubscriberMethod>
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }


        if (ignoreGeneratedIndex) {//是否每次都從反射去拿方法參數 , 默認爲false
            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;
        }
    }
 private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        //第一次打開相當於 FindState findState = new FindState()
        FindState findState = prepareFindState();
        //initForSubscriber方法做了以下3點
        //this.subscriberClass = clazz = subscriberClass;
        // skipSuperClasses = false;
        //subscriberInfo = null;
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) { //這裏相當於subscriberClass != null
            findState.subscriberInfo = getSubscriberInfo(findState);
            //在這裏相當於findState.subscriberInfo = null  會走else
            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 {
                ////將Subscribe 註解上的參數封裝成 SubscriberMethod 添加到 findState.subscriberMethods  List<SubscriberMethod> subscriberMethods
                findUsingReflectionInSingleClass(findState);
            }
            findState.moveToSuperclass();
        }
        //return封裝好的 annotation 參數ArrayList<subscriberMethods>
        return getMethodsAndRelease(findState);
    }

通過反射解析參數,已加上比較詳細的註釋

private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        try {
            // 獲取register的class對象的所有方法,包括私有和抽象
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            try {
                methods = findState.clazz.getMethods();
            } catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
                String msg = "Could not inspect methods of " + findState.clazz.getName();
                if (ignoreGeneratedIndex) {
                    msg += ". Please consider using EventBus annotation processor to avoid reflection.";
                } else {
                    msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
                }
                throw new EventBusException(msg, error);
            }
            findState.skipSuperClasses = true;
        }
        for (Method method : methods) {
            int modifiers = method.getModifiers();
            //篩選public方法,且沒有static abstract.. 等等修飾符
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                //獲取方法參數的class
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {//方法參數數目爲1,方法參數大於1不走
                    //獲取方法上Subscribe註解
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        //方法參數的class 只有一個,即 parameterTypes[0]
                        Class<?> eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {//true
                            ThreadMode threadMode = subscribeAnnotation.threadMode();//獲取將Subscribe Annotation的threadMode
                            //將Subscribe 註解上的參數封裝成 SubscriberMethod 添加到 findState.subscriberMethods  List<SubscriberMethod> subscriberMethods
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
                    //strictMethodVerification 是否驗證參數 拋異常 默認爲false
                } 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");
            }
        }
    }

處理事件

           1.優先級排序

  1. 處理粘性事件

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {        //方法參數class
        Class<?> eventType = subscriberMethod.eventType;
        // Subscription (register的class subscriber,註解參數subscriberMethod)
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //subscriptionsByEventType HashMap<方法參數Class<?>, CopyOnWriteArrayList<Subscription>>
        //Subscription (register的class 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);
            }
        }


        //subscriptions.size() == register了eventBus 的class 所有接受 event的方法數目
        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                //根據priority 優先級排序
                subscriptions.add(i, newSubscription);
                break;
            }
        }


        //typesBySubscriber HashMap key register EventBus 的 class value subscribedEvents<方法參數的class>
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        //方法參數的class
        subscribedEvents.add(eventType);


        if (subscriberMethod.sticky) {//處理粘性事件
            //把一個Event發送到一個還沒有初始化的Activity/Fragment,即尚未訂閱事件。
            // 那麼如果只是簡單的post一個事件,那麼是無法收到的,這時候,就需要用到粘性事件
            if (eventInheritance) {//默認爲true
                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                //stickyEvents = new ConcurrentHashMap<>();
                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的實例化,並將訂閱方法Subscribe註解解析,封裝成List<SubscriberMethod> findSubscriberMethods。

*取消註冊
避免內存泄漏

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


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

發送事件

public void post(Object event) {        //利用ThreadLocal將PostingThreadState線程安全
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        //將事件加入 eventQueue -> ArrayList<Object>
        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()) {
                    //發送事件 eventObject 對象
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }


private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        //eventObject對象的class
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {//默認爲true
            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));
            }
        }
    }


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

處理事件和發送事件
根據當前線程和訂閱的ThreadMode決定怎麼發送事件

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {        switch (subscription.subscriberMethod.threadMode) {
            case POSTING://相同線程 直接反射調用
                invokeSubscriber(subscription, event);
                break;
            case MAIN://主線程
                //MainThreadSupport - >isMainThread() -> looper == Looper.myLooper();
                if (isMainThread) {//判斷當前是否是主線程 ,主線程直接反射調用
                    invokeSubscriber(subscription, event);
                } else {
                    //new HandlerPoster .enqueue() handler切換主線程 send
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case MAIN_ORDERED://主線程有序 利用handler + eventBus 自己實現的 PendingPostQueue
                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) {//當前是主線程 newCachedThreadPool線程池執行
                    backgroundPoster.enqueue(subscription, event);
                } else {//不是主線程 直接執行
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC://異步 newCachedThreadPool線程池執行
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }

粘性事件

  • 應用場景
    我們要把一個Event發送到一個還沒有初始化的Activity/Fragment,即尚未訂閱事件。那麼如果只是簡單的post一個事件,那麼是無法收到的,這時候,就需要用到粘性事件,它可以幫我們解決這類問題。

  • 使用方式
    1.使用粘性事件時需要調用粘性註冊方法註冊
    2.訂閱方法聲明粘性事件

  • 粘性事件原理
    粘性事件發送時會將粘性事件存起來,當有類註冊方式爲粘性註冊,那麼就會檢查類中有沒有粘性訂閱方法,如果有,直接invoke發送事件。

if (subscriberMethod.sticky) {//處理粘性事件            //把一個Event發送到一個還沒有初始化的Activity/Fragment,即尚未訂閱事件。
            // 那麼如果只是簡單的post一個事件,那麼是無法收到的,這時候,就需要用到粘性事件
            if (eventInheritance) {//默認爲true
                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                //stickyEvents = new ConcurrentHashMap<>();
                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);
            }
        }
    Annotation的使用方式

前面分析了運用反射的使用方式和源碼,這是默認的實現,如果項目中有大量的訂閱事件的方法,會對項目運行時的性能產生一定的影響。其實除了在項目運行時通過反射查找訂閱事件的方法信息,查找訂閱事件方法信息的方式,生成一個輔助的索引類來保存這些信息,和編譯時註解-ButterKnife框架原理分析及手寫 原理類似。

基本使用
這裏我爲了方便修改和註釋內部源碼,直接將EventBus clone下來引入        

 implementation project(path: ':EventBus')   
  annotationProcessor  project(path: ':EventBusAnnotationProcessor')


android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                // 指定輔助索引類的名稱和包名
                arguments = [ eventBusIndex : 'com.ftys.eventbusdemo.EventBusIndex' ]
            }
        }
    }

Application中調用

EventBus.builder().addIndex(new EventBusIndex()).installDefaultEventBus();

生成的索引類結構如下

public class EventBusIndex implements SubscriberInfoIndex {    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;


    static {
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();


        putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("subscribeMethod", String.class, ThreadMode.MAIN),
        }));


    }


    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }


    @Override
    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}

手寫EventBus核心代碼

public class EventBus {    private static volatile EventBus mInstance;
    private List<SubscriberMethod> subscriberMethods = new ArrayList<>();
    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    private final Map<Object, List<Class<?>>> typesBySubscriber;
    private Executor executor;


    private EventBus() {
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        executor = Executors.newCachedThreadPool();
    }


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


    public void register(Object subscriber) {
        Class<?> registerClass = subscriber.getClass();
        Method[] methods = registerClass.getDeclaredMethods();
        for (Method method : methods) {
            Subscribe subscribe = method.getAnnotation(Subscribe.class);
            if (subscribe != null) {
                Class<?>[] parameterClasses = method.getParameterTypes();
                if (parameterClasses.length == 1) {
                    SubscriberMethod subscriberMethod = new SubscriberMethod(method, parameterClasses[0],
                            subscribe.threadMode(), subscribe.priority(), subscribe.sticky());
                    if (!subscriberMethods.contains(subscriberMethod)) {
                        subscriberMethods.add(subscriberMethod);
                    }
                }
            }
        }
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }


    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);
        }
        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                //根據priority 優先級排序
                subscriptions.add(i, newSubscription);
                break;
            }
        }


        //typesBySubscriber HashMap key register EventBus 的 class value subscribedEvents<方法參數的class>
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        //方法參數的class
        subscribedEvents.add(eventType);
    }


    private List<Object> eventQueueOut = new ArrayList<>();


    public void post(Object event) {
        List<Object> eventQueue = eventQueueOut;
        eventQueue.add(event);
        while (!eventQueue.isEmpty()) {
            //發送事件 eventObject 對象
            postSingleEvent(eventQueue.remove(0));
        }
    }


    private void postSingleEvent(Object event) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(event.getClass());
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                postToSubscription(subscription, event);
            }
        }
    }


    private void postToSubscription(final Subscription subscription, final Object event) {
        boolean isMainThread = (Looper.myLooper() == Looper.getMainLooper());
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING://相同線程 直接反射調用
                invokeSubscriber(subscription, event);
                break;
            case MAIN://主線程
                //MainThreadSupport - >isMainThread() -> looper == Looper.myLooper();
                if (isMainThread) {//判斷當前是否是主線程 ,主線程直接反射調用
                    invokeSubscriber(subscription, event);
                } else {
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            invokeSubscriber(subscription, event);
                        }
                    });
                }
                break;
            case MAIN_ORDERED://主線程有序 利用handler + eventBus 自己實現的 PendingPostQueue
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        invokeSubscriber(subscription, event);
                    }
                });
                break;
            case BACKGROUND://子線程
                if (isMainThread) {//當前是主線程 newCachedThreadPool線程池執行
                    executor.execute(new Runnable() {
                        @Override
                        public void run() {
                            invokeSubscriber(subscription, event);
                        }
                    });
                } else {//不是主線程 直接執行
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC://異步 newCachedThreadPool線程池執行
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        invokeSubscriber(subscription, event);
                    }
                });
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }


    private void invokeSubscriber(Subscription subscription, Object event) {
        try {
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }


    public void unregister(Object subscriber) {
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                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--;
                        }
                    }
                }
            }
            typesBySubscriber.remove(subscriber);
        }
    }
}

總結
EventBus使用發佈者/訂閱者模式實現鬆散耦合,簡化組件之間的通信。使用簡單,效率高,體積小。原理不算複雜,但是源碼有非常非常多的細節處理值得我們去學習。

關注我獲取更多知識或者投稿

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章