Eventbus3.0 源码解析

这里我想记录下 eventbus3.0的使用 以及工作原理

首先 我们导入eventbus3.0的依赖:

在gradle中 写入

compile 'org.greenrobot:eventbus:3.0.0'

在代码中注册:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    EventBus.getDefault().register(this);//注册EventBus
    registerReceiver(receiver, getFilter());

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    initView();
    setDatabase();

}

在销毁时反注册:

@Override
protected void onDestroy() {
    unregisterReceiver(receiver);
    super.onDestroy();
    EventBus.getDefault().unregister(this);
}

在代码中发送消息:

EventBus.getDefault().post(new MyEvent("ssss"));
这里 需要自己写一个Event的类 这个类主要用于传递一些你想传递的简易信息

public class MyEvent {
    public String msg;
    public MyEvent(String msg) {
        this.msg = msg;
    }
}

接下来是接收消息这个很关键:

@Subscribe(threadMode = ThreadMode.POSTING)
public void onEventMainThread(MyEvent event) {
    Toast.makeText(MainActivity.this,event.msg+"ads",Toast.LENGTH_LONG).show();
}
其中 

@Subscribe(threadMode = ThreadMode.POSTING)
这里的ThresdMode有四种方式 我们翻开看一下

public enum ThreadMode {
    /**
     * Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery
     * implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
     * simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers
     * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
     */
    POSTING,

    /**
     * Subscriber will be called in Android's main thread (sometimes referred to as UI thread). If the posting thread is
     * the main thread, event handler methods will be called directly. Event handlers using this mode must return
     * quickly to avoid blocking the main thread.
     */
    MAIN,

    /**
     * Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods
     * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
     * background thread, that will deliver all its events sequentially. Event handlers using this mode should try to
     * return quickly to avoid blocking the background thread.
     */
    BACKGROUND,

    /**
     * Event handler methods are called in a separate thread. This is always independent from the posting thread and the
     * main thread. Posting events never wait for event handler methods using this mode. Event handler methods should
     * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
     * of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus
     * uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
     */
    ASYNC
}
其中的意思是:

MAIN UI主线程
BACKGROUND 后台线程
POSTING 和发布者处在同一个线程
ASYNC 异步线程

所以当我们选择的接收模式不同时 就关系到我们能不能接收到post事件。


接下来我们来看看EventBus3.0 的源码 等我们看完源码之后  我们会对EventBus有个新的认知

首先我们从EventBus.getDefault().register(this)入手,

EventBus.getDefault()里面:

/** 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是单例模式的 这样也有助于消息的管理

我们再看register:

/**
 * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
 * are no longer interested in receiving events.
 * 

* Subscribers have event handling methods that must be annotated by {@link Subscribe}. * The {@link Subscribe} annotation also allows configuration like {@link * ThreadMode} and priority. */ public void register(Object subscriber) { Class subscriberClass = subscriber.getClass(); List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } } }

从这段代码我们可以看出首先获取订阅者的类对象Class subscriberClass = subscriber.getClass();

在下面那句代码中 用到了这个对象

我们发现下面有个SubscriberMethod的集合 还有个叫subscriberMethodFinder的类 

那么这些东西究竟是干什么的呢

我们继续探寻

public class SubscriberMethod {
    final Method method;
    final ThreadMode threadMode;
    final Class eventType;
    final int priority;
    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;
    }
 从SubscriberMethod 我们可以看到 这是一个保存方法 线程模式 等等的类 那我们看看后面那个subscriberMethodFinder调用的方法 先逐个击破:

List findSubscriberMethods(Class subscriberClass) {
    List 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;
    }
}
private static final Map, List> METHOD_CACHE = new ConcurrentHashMap<>();
我们可以看到 首先是从缓存中读取 如果没有 就走到下面

if (ignoreGeneratedIndex) {
    subscriberMethods = findUsingReflection(subscriberClass);
} else {
    subscriberMethods = findUsingInfo(subscriberClass);
}
这里是说是否忽略注解器生成的MyEventBusIndex类  如果忽略就从反射拿去 如果不忽略 就直接从注解器拿取

拿到之后就保存进缓存

那我们看看这两个方法

我们先来看通过反射的方法 

private List findUsingReflection(Class subscriberClass) {
    FindState findState = prepareFindState();
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        findUsingReflectionInSingleClass(findState);
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}
一个一个了解过去我们发现   FindState只用于储存一些信息 getMethodsAndRelease只是把FindState里面的SubscriberMethod集合返回 那么 关键就在于
findUsingReflectionInSingleClass(findState);

我们查看这个方法

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) {
        // 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();
        // 必须被public修饰,而且不能为MODIFIERS_IGNORE
        // MODIFIERS_IGNORE定义为ABSTRACTSTATICBRIDGESYNTHETIC        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            // 获取方法所有参数类型
            Class[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 1) {
                // 是否有Subscribe注解标签
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                if (subscribeAnnotation != null) {
                    // 带有Subscribe注解标签的方法的第一个参数类型
                    Class eventType = parameterTypes[0];
                    // 关联method, eventTypeanyMethodByEventType
                    if (findState.checkAdd(method, eventType)) {
                        ThreadMode threadMode = subscribeAnnotation.threadMode();
                        // 构造SubscriberMethod,并且添加到findState.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");
        }
    }
}
走完这里 我们发现只要类中带有Subscribe注解标签的方法都会被构建成一个SubscribeMethod保存到findstate

最后在

getMethodsAndRelease(findState)

中将集合返回给上一层 

 那findUsingInfo(subscriberClass);又如何走的呢:

private List findUsingInfo(Class subscriberClass) {
    FindState findState = prepareFindState();
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        findState.subscriberInfo = getSubscriberInfo(findState);
        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 {
            findUsingReflectionInSingleClass(findState);
        }
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}
从代码一步一步看下来

void initForSubscriber(Class subscriberClass) {
    this.subscriberClass = clazz = subscriberClass;
    skipSuperClasses = false;
    subscriberInfo = null;
}

我们很容易发现 findState.subscriberInfo 将会默认为空 然后会走到

findUsingReflectionInSingleClass(findState);

这个方法 那么又和上面一样了  就这样 我们注册的时候得到了所有标有Subscribe 方法的集合  

接着我们接着回到注册来看:

synchronized (this) {
    for (SubscriberMethod subscriberMethod : subscriberMethods) {
        subscribe(subscriber, subscriberMethod);
    }
}
然后遍历执行subscribe()方法。看样子应该是遍历List,然后将订阅者和订阅事件绑定。

// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    // 获取订阅事件的类型,即订阅方法中的唯一参数类型
    Class eventType = subscriberMethod.eventType;
    // 用订阅者和订阅方法构造一个Subscription对象
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    // 查找所有的订阅了订阅事件的订阅者
    CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
    // 没有订阅者订阅过则新建个CopyOnWriteArrayList,并putsubscriptionsByEventType PS:CopyOnWriteArrayList支持并发读写
    if (subscriptions == null) {
        subscriptions = new CopyOnWriteArrayList<>();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        // 订阅者List不为空,而且已经包含了newSubscription,则会抛出异常。即:订阅者不能重复订阅同一事件
        if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                    + eventType);
        }
    }

    int size = subscriptions.size();
    // 根据订阅者优先级,增加到订阅者列表subscriptions的相应位置
    for (int i = 0; i <= size; i++) {
        if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }
    // 获取订阅者所有订阅事件的列表,默认为null
    List> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    // 将订阅事件添加进对应订阅者的订阅列表
    subscribedEvents.add(eventType);
    // sticky默认为false
    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);
        }
    }
}
Register()其实只做了三件事:
1. 查找订阅者所有的订阅事件
2. 将订阅事件作为key,所有订阅了此订阅事件的订阅者作为value存放进subscriptionsByEventType
3. 将订阅者作为key,订阅者的所有订阅事件作为value存放进typesBySubscriber

接下来Post():

public void post(Object event) {
    // 依据不同的线程获取相应的刚初始化的PostingThreadState
    PostingThreadState postingState = currentPostingThreadState.get();
    List eventQueue = postingState.eventQueue;
    // event加入到postingState.eventQueue
    eventQueue.add(event);
    // isPosting默认false
    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 {
            // 遍历发送eventQueue中的event
            while (!eventQueue.isEmpty()) {
                postSingleEvent(eventQueue.remove(0), postingState);
            }
        } finally {
            postingState.isPosting = false;
            postingState.isMainThread = false;
        }
    }
} 接着进入postSingleEvent: 
  

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    // 获取event的类型
    Class eventClass = event.getClass();
    boolean subscriptionFound = false;
    // eventInheritance默认为true
    if (eventInheritance) {
        // 依据订阅事件类型,将订阅事件类型及所有父类添加进eventTypes。详情见下文lookupAllEventTypes()分析
        List> eventTypes = lookupAllEventTypes(eventClass);
        int countTypes = eventTypes.size();
        // 遍历countTypes,通过调用postSingleEventForEventType()方法通知所有订阅者
        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) {
            Log.d(TAG, "No subscribers registered for event " + eventClass);
        }
        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                eventClass != SubscriberExceptionEvent.class) {
            post(new NoSubscriberEvent(this, event));
        }
    }
}

private static List> lookupAllEventTypes(Class eventClass) {
    synchronized (eventTypesCache) {
        // 根据订阅事件查找所有自身及父类,eventTypes默认为null
        List> eventTypes = eventTypesCache.get(eventClass);
        if (eventTypes == null) {
            eventTypes = new ArrayList<>();
            Class clazz = eventClass;
            while (clazz != null) {
                // 将订阅事件添加进eventTypes
                eventTypes.add(clazz);
                // 遍历订阅事件的所有父类,依次添加进eventTypes
                addInterfaces(eventTypes, clazz.getInterfaces());
                clazz = clazz.getSuperclass();
            }
            // 将订阅事件和包含订阅事件自身及所有父类的eventTypes添加进eventTypesCache
            eventTypesCache.put(eventClass, eventTypes);
        }
        return eventTypes;
    }
}

/** Recurses through super interfaces. */
static void addInterfaces(List> eventTypes, Class[] interfaces) {
    for (Class interfaceClass : interfaces) {
        if (!eventTypes.contains(interfaceClass)) {
            eventTypes.add(interfaceClass);
            addInterfaces(eventTypes, interfaceClass.getInterfaces());
        }
    }
}

下面看postSingleEventForEventType:

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) {
    CopyOnWriteArrayList 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 {
                // 参数解释:subscription-被遍历到的订阅者;event-订阅事件参数(子类);
                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;
}
注意看这里:

subscriptions = subscriptionsByEventType.get(eventClass);
在注册的时候

将订阅事件作为key,所有订阅了此订阅事件的订阅者作为value存放进subscriptionsByEventType


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 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);
    }
}
首先根据ThreadMode确定分发类型。这里以最常用的Main为例,其余两个Poster同理。如果是isMainThread=true,那么直接调用invokeSubscriber(),否则调用mainThreadPoster.enqueue()

void invokeSubscriber(Subscription subscription, Object event) {
    try {
        subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
	//反射调用
    } catch (InvocationTargetException e) {
        handleSubscriberException(subscription, event, e.getCause());
    } catch (IllegalAccessException e) {
        throw new IllegalStateException("Unexpected exception", e);
    }
}

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");
            }
        }
    }
}
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);
}
尝试从pendingPostPool中获取pendingPost,没有则直接new PendingPost


@Override
public void handleMessage(Message msg) {
    boolean rescheduled = false;
    try {
        long started = SystemClock.uptimeMillis();
// 已经切换到主线程 
        while (true) {
	 // 遍历获取queue中的PendingPost对象
            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
            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
    PendingPost.releasePendingPost(pendingPost);
    if (subscription.active) {
        // 反射调用订阅者的订阅事件
        invokeSubscriber(subscription, event);
    }
}

void invokeSubscriber(Subscription subscription, Object event) {
    try {
        subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
    } catch (InvocationTargetException e) {
        handleSubscriberException(subscription, event, e.getCause());
    } catch (IllegalAccessException e) {
        throw new IllegalStateException("Unexpected exception", e);
    }
}
Post()也只做了三件事
1. 根据订阅事件在subscriptionsByEventType中查找相应的订阅者
2. 分发订阅者的订阅事件调用线程
3. 通过反射调用订阅者的订阅事件


最后:

/** Unregisters the given subscriber from all event classes. */
public synchronized void unregister(Object subscriber) {
    List> 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());
    }
}

/** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
private void unsubscribeByEventType(Object subscriber, Class eventType) {
    List 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--;
            }
        }
    }
}
unregister():

将subscriptionsByEventType,typesBySubscriber的key和value移除清空。

好了 写到这里!

你可能感兴趣的:(安卓日常笔记)