EventBus源碼分析

EventBus源碼分析

1、源碼分析要點

EventBus是觀察者模式,是一對多,一般源碼分析的重點在register方法上,分析的核心應在在消息隊列上PendingPostQueue

1、消息隊列

PendingPostQueue{
    void enqueue(PendingPost pendingPost)//加入消息
    PendingPost poll()//取出消息
}

2、處理消息核心 五種策略

interface Poster {
    void enqueue(Subscription subscription, Object event);//加入消息    
}

1、Poster消息隊列存取

class XXXPoster implements Runnable, Poster {

    public void enqueue(Subscription subscription, Object event) {
        //插入消息
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        //運行
        eventBus.getExecutorService().execute(this);
    }

    @Override
    public void run() {
        //取出消息
        PendingPost pendingPost = queue.poll();
        //處理消息
        eventBus.invokeSubscriber(pendingPost);
    }

}

2、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);
            }
        }
    }
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);
        }
        
        //注冊該類
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);
    }

找該類所有注解方法

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        subscriberMethods = findUsingReflection(subscriberClass);
        return subscriberMethods;
    }

//尋找注解實現(xiàn)

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

3、post放入消息流程

post(event)-->postSingleEvent()-->postSingleEventForEventType()-->postToSubscription()-->XXXPoster.enqueue(subscription, event)

1、通過event尋找注冊類

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
            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);
            }
}

通過event尋找該注冊類函數(shù)清單,發(fā)送

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            //通過發(fā)送事件類型尋找注冊表
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
            //遍歷整個列表發(fā)送消息
            for (Subscription subscription : subscriptions) {
                postingState.event = event;
                postingState.subscription = subscription;
                //處理消息
                postToSubscription(subscription, event, postingState.isMainThread); 
            }
            return true;
        }
        return false;
    }

4、普通post與postSticky區(qū)別

1、postSticky 緩存最新的一個事件
2、register后,postSticky 自動觸發(fā)一遍該類的緩存的事件

public void postSticky(Object event) {
        synchronized (stickyEvents) {
            stickyEvents.put(event.getClass(), event);
        }
        post(event);
    }
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    if (subscriberMethod.sticky) {
        Object stickyEvent = stickyEvents.get(eventType);
        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
    }
}

定制化RxBus

設計rxbus重點

1、調用方式與EventBus一致,降低使用成本
2、rxjava是觀察者模式,可以替換Eventbus消息隊列和處理消息的策略模式
3、支持線程安全
4、支持黏性事件

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • EventBus源碼分析(一) EventBus官方介紹為一個為Android系統(tǒng)優(yōu)化的事件訂閱總線,它不僅可以很...
    蕉下孤客閱讀 4,107評論 4 42
  • 前面對EventBus 的簡單實用寫了一篇,相信大家都會使用,如果使用的還不熟,或者不夠6,可以花2分鐘瞄一眼:h...
    gogoingmonkey閱讀 358評論 0 0
  • EventBus源碼分析 Android開發(fā)中我們最常用到的可以說就是EventBus了,今天我們來深入研究一下E...
    BlackFlag閱讀 547評論 3 4
  • 面試有一種技巧據(jù)說叫做反客為主,當遇到Activity-Fragment通信,甚至模塊化開發(fā)時的通信問題等等,可以...
    TruthKeeper閱讀 603評論 0 6
  • 好久沒寫博文了,這幾個月復習了很多東西,新年在老家閑的慌啊,我這么愛學習的人只能學習了哈啊哈哈哈哈哈哈(滑稽臉)。...
    minminaya閱讀 1,029評論 0 0

友情鏈接更多精彩內容