EventBus的源码分析

来源:互联网 发布:淘宝人生txt下载 编辑:程序博客网 时间:2024/05/16 16:19

EventBus的初始化

 /** 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;    }
可以看出EventBus是单例模式

/**     * Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a     * central bus, consider {@link #getDefault()}.     */    public EventBus() {        this(DEFAULT_BUILDER);    }    EventBus(EventBusBuilder builder) {        subscriptionsByEventType = new HashMap<>();        typesBySubscriber = new HashMap<>();        stickyEvents = new ConcurrentHashMap<>();        mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);        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;    }

EventBus是通过Builder来进行构建,一般使用默认的构建

subscriptionsByEventType : 内部是一个Map集合,可以根据EventType查找订阅事件
typesBySubscriber : 根据我们的订阅对象找到EventType
stickyEvents : 粘性事件的缓存

eventInheritance :默认为true的,官方文档解释,为true时,订阅函数的参数类型的父类也会受到消息,设置off会提高发布的效率,但是本身所占cpu就是很小的一部分,所以一般默认设置true


事件投递者 : mainThreadPoster,backgroundPoster,asyncPoster 根据订阅注解ThreadMode去选择不同的投递者,不同投递者投递事件,接收函数会执行在不同的线程中
subscriberMethodFinder :查找方法用的,内部维护了一个订阅方法的集合


注册

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

那SubscriberMethod也就是订阅者接收事件的方法

public class SubscriberMethod {    final Method method;    final ThreadMode threadMode;    final Class<?> eventType;    final int priority;    final boolean sticky;    /** Used for efficient comparison */    String methodString;
可以看出其实就是订阅方法上面的注解的封装

查找订阅的方法

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {        //取以订阅者为key的缓存,有的话直接返回        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);        if (subscriberMethods != null) {            return subscriberMethods;        }        //是否忽略编译时注解生成的文件,为true则为反射生成         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;        }    }

首先会从缓存中查找,没有的话通过ignoreGeneratedIndex的值采取不同方法查找订阅方法。下面看看
 private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {        FindState findState = prepareFindState();        findState.initForSubscriber(subscriberClass);        while (findState.clazz != null) {            findUsingReflectionInSingleClass(findState);            findState.moveToSuperclass();        }        return getMethodsAndRelease(findState);    }
看看FindState对象,也就是对找到的方法,订阅者等的封装。findState.initForSubscriber(subscriberClass)也就是把订阅者传给findState对象,接下来通过findUsingReflectionInSingleClass(findState)来不断查找订阅者以及父类的订阅方法。

 static class FindState {        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();        final Map<Class, Object> anyMethodByEventType = new HashMap<>();        final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();        final StringBuilder methodKeyBuilder = new StringBuilder(128);        Class<?> subscriberClass;        Class<?> clazz;        boolean skipSuperClasses;        SubscriberInfo subscriberInfo;}
通过反射,寻找接收消息的方法 SubscriberMethodFinder.findUsingReflection

private void findUsingReflectionInSingleClass(FindState findState) {        Method[] methods;        try {            // This is faster than getMethods, especially when subscribers are fat classes like Activities            //findState.clazz为订阅者或者其父类            methods = findState.clazz.getDeclaredMethods();        } catch (Throwable th) {            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149            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();                            //封装SubscriberMethod,添加到findState.subscriberMethods                            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");            }        }    }

以上代码就是遍历订阅者里面的方法,看有没有注解,有的话就解析注解,最后将找到的订阅方法的集合封装到FindState对象中的subscriberMethods集合中。

再看findUsingReflection()方法的最后,返回了getMethodsAndRelease(FindState)

private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {        List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);        findState.recycle();        synchronized (FIND_STATE_POOL) {            for (int i = 0; i < POOL_SIZE; i++) {                if (FIND_STATE_POOL[i] == null) {                    FIND_STATE_POOL[i] = findState;                    break;                }            }        }        return subscriberMethods;    }
可以看到解析完后把订阅方法赋给List的集合返回,把findState对象回收,没有浪费内存。


订阅

 // Must be called in synchronized block    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {        Class<?> eventType = subscriberMethod.eventType;        //将订阅者和订阅方法封装成一个Subscription        //之所以要封装是由于EventBus 支持仅仅解绑订阅者中的某一个方法。        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);        //根据eventType从缓存中取出subscriptions        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;            }        }        //根据订阅者查找EventType的缓存,在unregister的时候解绑用        List<Class<?>> 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<Class>).                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();                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.post()

 /** Posts the given event to the event bus. */    public void post(Object event) {        // //每个线程中都维护了一个投递的状态        //使用 ThradLocal 根据线程拿到当前线程的PostingThreadState        PostingThreadState postingState = currentPostingThreadState.get();        List<Object> eventQueue = postingState.eventQueue;        eventQueue.add(event);        if (!postingState.isPosting) {            postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();            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;            }        }    }
上面代码postSingleEvent()方法依次点进去,最终会执行postToSubscription(subscription, event, postingState.isMainThread);

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {        //这里会根据threadMode执行在不同的线程中        switch (subscription.subscriberMethod.threadMode) {            case POSTING:                invokeSubscriber(subscription, event);                break;            case MAIN:                if (isMainThread) {                    invokeSubscriber(subscription, event);                } else {                    mainThreadPoster.enqueue(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的情况,当是主线程时直接通过反射运行订阅方法,否则执行mainThreadPoster.enqueue(subscription, event),mainThreadPoster将订阅事件入队列,将事件发送到主线程。

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);        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");                }            }        }    }    @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                        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;        }    }}
在EventBus初始化的时候,mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10)已经获取了主线程的Looper


反注册

/** 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 {            Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());        }    }
就是通过订阅者查找订阅类型,然后去解绑订阅事件

粘性事件

在注册执行订阅subscribe(subscriber, subscriberMethod)时有下面一段代码

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<Class>).                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();                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);            }        }
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.            postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());        }    }

也就是在注册的时候指定为粘性事件,在订阅时就立即调用发布,发布的是从缓存中取出的订阅事件










0 0
原创粉丝点击