Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> EventBus的源碼分析

EventBus的源碼分析

編輯:關於Android編程

通過這片文章可以回答以下兩個問題
1、為啥EventBus的事件處理方法必須申明為Public?但是我用protected也是OK的
2、粘性事件的原理,為啥發送多次Event,只有最新的event能夠得到處理?

EventBus類圖

這裡寫圖片描述vc+88rWloaPG5NbQ1+66y9DEtcTA4M6qRXZlbnRCdXO6zVN1YnNjcmliZXJNZXRob2RGSW5kZXKjrEV2ZW50QnVzzeqzycHLvvi087K/t9ajqNeisuGhoreisryhoru6tOahoreiyeS199PD16Ky4dXft723qLXIo6m1xMLfvK25psTco6xTdWJzY3JpYmVyTWV0aG9kRkluZGVy1PLTw9PasunV0teisuHA4LXEysK8/re9t6iho7jDwODNvEV2ZW50QnVzyc+3vbXEwODW99Kq08PT2s3qs8lFdmVudEJ1c7XE16Ky4bmk1/ejrLb4z8K3vbXEveG5+1Bvc3RlctTy08PT2kV2ZW50QnVztcTKwrz+t6KyvKGjPC9wPg0KPGgyIGlkPQ=="eventbus流程圖">EventBus流程圖

這裡寫圖片描述
這裡寫圖片描述
1)EventBus的注冊過程中, 通過反射的方式找到注冊類中所有的事件處理方法(@Subscriber標注的public方法),再將注冊類的信息保存在HashMap中。如果發現注冊類中的某個方法是sticky的,那麼將會直接進入事件發布的流程
2)EventBus的事件發布過程中,不管采用哪一種線程模型,最重都會調用EventBus類中的invokeSubscriber()方法。如果客戶端發送的是一個Sticky事件,EventBus將event事件存入到粘性事件緩存stickyEvents中,然後回到普通事件的處理流程上

源碼分析

getDefault()方法,獲得默認的EventBus實例

//默認情況下,采用單例模式,線程安全。
//也可以不用單例模式,EventBus的構造方法是public的,因此初始化自己的EventBus對象
public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

register()方法,訂閱者注冊

//subscriber就是訂閱發布 模式中的訂閱著,如我們的Activity
public void register(Object subscriber) {
    Class subscriberClass = subscriber.getClass();//獲取訂閱者的Class類對象
    List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//獲取該類中的事件方法(@subscribe標簽),SubscriberMethod類包含了注冊者的類、方法、sticky、線程模式等信息
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);//緩存注冊者信息
        }
    }
}

findSubscriberMethods()方法,獲得訂閱者中@Subscribe標識的方法

List findSubscriberMethods(Class subscriberClass) {
    List subscriberMethods = METHOD_CACHE.get(subscriberClass);//從緩存中找
    if (subscriberMethods != null) {
        return subscriberMethods;//緩存命中,直接返回
    }

    //ignoreGeneratedIndex默認情況為false,但都會走到findUsingReflectionInSingleClass方法中,通過反射來找到@Subscribe標識的方法
    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;
    }
}
//通過反射來處理,找到訂閱者中@Subscribe標識的方法
private void findUsingReflectionInSingleClass(FindState findState) {
    Method[] methods;
    try {
        // 獲取注冊類的所有申明方法(非繼承方法),該方法的效率比getMehtods()高
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
        methods = findState.clazz.getMethods();
        findState.skipSuperClasses = true;
    }
    for (Method method : methods) {
        int modifiers = method.getModifiers();//方法的修飾符:public
        //找到public修飾的方法,這裡奇怪的是,protected的方法通過反射得到的方法修飾符也是public,這就是為什麼protected修飾的方法也能使用的原因!!
        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            //找到參數個數為1的方法
            Class[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 1) {
                //找到注解@Subscribe標識的方法
                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()方法,在找到注冊類的方法後,就需要對這些方法也注冊,存入緩存中

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    Class eventType = subscriberMethod.eventType;//消息事件的類型
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);//Subscription類封裝了注冊者和它的一個方法
    CopyOnWriteArrayList 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;
        }
    }

    //向緩存中添加subscriber所對應的Event。感覺typesBySubscriber沒啥用?
    List> 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).
            Set, Object>> entries = stickyEvents.entrySet();
            for (Map.Entry, 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);//該方法將會直接跳轉到事件發布歷程中執行
        }
    }
}

post()方法,發布者發布消息事件

//currentPostingThreadState是一個ThredLocal變量,線程內部共享數據,線程間安全
private final ThreadLocal currentPostingThreadState = new ThreadLocal() {
    @Override
    protected PostingThreadState initialValue() {
        return new PostingThreadState();
    }
};

//發布event粘性事件
public void postSticky(Object event) {
    synchronized (stickyEvents) {
        //stickyEvents是ConcurrentHashMap,每次往map中put鍵值對,會覆蓋具有相同event.getClass()的值,因此導致即使發布多次粘性事件,也只會處理最新的那一個
        //換句話即:同一個event類,在緩存中只會保存一個粘性事件!
        stickyEvents.put(event.getClass(), event);
    }
    post(event);
}
//發布event事件
public void post(Object event) {
    PostingThreadState postingState = currentPostingThreadState.get();
    List

AsyncPoster類,實現了Runnable接口

class AsyncPoster implements Runnable {
    private final PendingPostQueue queue;
    private final EventBus eventBus;

    AsyncPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    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();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        eventBus.invokeSubscriber(pendingPost);//調用EventBus的反射方法
    }

}

BackgroundPoster類,雖然也實現了Runnable接口,雖然也在子線程中執行EventBus的反射回調方法。但是與AsyncPoster類不同的是:
1)AsyncPoster類每次任務都會新建一個線程,並發執行隊列中的任務
2)而BackgroundPoster類只會新建一個子線程,隊列中的任務,只會順序執行。

final class BackgroundPoster implements Runnable {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    private volatile boolean executorRunning;

    BackgroundPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);
            }
        }
    }

    @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) {
                Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

}

mainThreadPoster是HandlerPoster變量,他繼承Handler,不難猜出,他通過Handler+Looper機制,來實現主線程調用

mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);//綁定主線程的Looper


final class HandlerPoster extends Handler {

    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

    HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);//綁定主線程的Looper
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }

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

    //處理event事件,調用EventBus的invokeSubscriber反射回調
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            while (true) {
                PendingPost pendingPost = queue.poll();
                if (pendingPost == null) {
                    synchronized (this) {
                        // 雙重判0,線程安全
                        pendingPost = queue.poll();
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                eventBus.invokeSubscriber(pendingPost);//調用EventBus的反射方法
                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;
        }
    }
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved