目錄
-
EventBus優(yōu)缺點(diǎn)
-
EventBus基本用法
-
EventBus源碼解析
一、EventBus優(yōu)缺點(diǎn)對比
優(yōu)點(diǎn):
1壶谒、是一個輕量級的事件總線橱脸,使用方便
2、去除應(yīng)用中大量的回調(diào)抱冷,能一定程度解耦各組件
缺點(diǎn):
1崔列、代碼可讀性降低,大量的事件使代碼解耦的同時旺遮,聯(lián)系也變得弱了
2赵讯、不支持跨進(jìn)程通訊(廣播支持)
二、EventBus使用
首先使用別人家的東西第一步導(dǎo)包:
implementation 'org.greenrobot:eventbus:3.1.1'
EventBus使用相對簡單耿眉,github下面就有使用步驟边翼,我們直接參照
1.定義傳遞的時間對象,該對象就是步驟2中接收的對象鸣剪,也是步驟3中發(fā)送的事件
2.(1)定義接收事件方法(即訂閱方法)组底,該方法用注解@Subscribe修飾丈积,并通過threadMode指定其分發(fā)到的線程 (2)在定義接收方法的類中(Android中一般為activity、fragment或service)注冊與解注冊EventBus
3.在任何地方通過post方法發(fā)送你的事件
通過以上三個步驟就可以使用EventBus進(jìn)行事件傳遞
三债鸡、源碼分析
在分析源碼之前我們有幾個問題需要拋出
1江滨、EventBus是如何確定哪些方法是訂閱方法的
2、EventBus是如何做線程切換的
3厌均、EventBus為什么不支持跨進(jìn)程
如果讀完這篇源碼分析能解決以上問題就足夠了
1.EventBus對象
EventBus.java
static volatile EventBus defaultInstance;
//雙重檢查鎖獲取單例對象
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;
}
EventBus.getDefault()通過雙重檢查鎖獲取單例對象唬滑,并通過volatile關(guān)鍵字保證單例對象的可見性
2.register與unregister
(1) register
/**
* Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
* are no longer interested in receiving events.
* <p/>
* 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();
//1、SubscriberMethod為已訂閱的方法莫秆,這里通過類對象查找到該類所有訂閱方法
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
//2间雀、遍歷該類所有已訂閱方法,并訂閱
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
上面代碼也很好理解镊屎,
(1)根據(jù)類對象獲得該類中定義的訂閱方法信息
(2)遍歷所有訂閱方法執(zhí)行訂閱
下面針對這兩個問題我們具體進(jìn)去看看
SubscriberMethodFinder.java
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> 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;
}
}
這里主要根據(jù)ignoreGeneratedIndex標(biāo)志位判斷調(diào)用哪個方法獲取訂閱方法惹挟,ignoreGeneratedIndex標(biāo)志位使用的是EventBusBuilder的默認(rèn)實(shí)例,EventBusBuilder的ignoreGeneratedIndex默認(rèn)為false,因此這里會執(zhí)行findUsingInfo(subscriberClass)
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
//1缝驳、循環(huán)遍歷該類及其父類的方法
while (findState.clazz != null) {
//獲取已訂閱信息緩存
findState.subscriberInfo = getSubscriberInfo(findState);
//2连锯、判斷訂閱方法是否為空,為空通過反射獲取訂閱方法用狱;不為空直接使用緩存
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);
}
這里通過FindState對象保存需要的信息运怖,通過遍歷該類及其所有父類獲取所有訂閱方法,訂閱信息如已存在于緩存中夏伊,直接取出使用;如果為緩存中沒有摇展,使用反射獲取。下面我們著重看看反射獲取訂閱方法的相關(guān)內(nèi)容
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) {
//1溺忧、判斷方法必須是public修飾咏连,且不是static也不是abstract修飾的
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
//2鲁森、獲取方法入?yún)⒙⒍袛嗳雲(yún)⒅挥幸粋€,繼續(xù)執(zhí)行(表示訂閱方法只能有一個入?yún)ⅲ? Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
//3痛垛、獲取注解草慧,判斷注解不為空則繼續(xù)執(zhí)行(表示訂閱方法必須由Subscribe注解)
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
//獲取直接中threadMode參數(shù),該參數(shù)為訂閱方法執(zhí)行的線程定義
ThreadMode threadMode = subscribeAnnotation.threadMode();
//4榜晦、以上全部符合要求乾胶,將信息保存到findState中
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");
}
}
}
通過findUsingReflectionInSingleClass方法我們可以看到EventBus對訂閱方法的約束:
1抖剿、訂閱方法必須是public修飾的脑融,且不能用static、abstract修飾
2缩宜、訂閱方法的參數(shù)只能是一個肘迎,即事件對象
3、訂閱方法必須有@ Subscribe注解 锻煌,threadMode默認(rèn)為POSTING
分析完訂閱方法的獲取妓布,我們具體看看這些方法是如何訂閱的
//根據(jù)事件類型(eventType),保存所有eventType的訂閱方法
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//根據(jù)訂閱對象(subscriber)宋梧,保存該訂閱對象的所有事件
private final Map<Object, List<Class<?>>> typesBySubscriber;
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
//訂閱方法的封裝對象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//將所有事件類型的訂閱方法保存在一個集合中
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
/**
* 1匣沼、判斷該事件是否已有存儲訂閱方法信息的容器;
* 沒有則創(chuàng)建容器,并將容器存入subscriptionsByEventType中捂龄;
* 若存在判斷該訂閱方法(newSubscription)是否已在容器中释涛,已在拋出重復(fù)注冊異常
*/
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();
//2、根據(jù)優(yōu)先級將訂閱方法(newSubscription)插入容器對用的位置
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//3倦沧、根據(jù)注冊對象subscriber保存該對象所有事件(實(shí)際subscribedEvents緩存的信息代表該注冊對象subscriber是否被注冊)
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);
}
}
}
subscribe方法總共有做了幾件事:
1唇撬、通過eventType將該eventType下所有訂閱方法保存在subscriptionsByEventType中
2、通過訂閱對象將該訂閱對象所擁有的所有eventType對象保存在typesBySubscriber中
3展融、判斷是否是粘性事件并做對應(yīng)的處理(這里我們不做分析)
看到這里肯定有很多的疑惑:
1窖认、subscriptionsByEventType這個map是做什么的?
2告希、typesBySubscriber這個map又是做什么的耀态?
這里我們先揭曉答案:
1、subscriptionsByEventType實(shí)際是通過eventType保存該eventType所有的訂閱方法暂雹,這里理解為實(shí)際的訂閱;待事件分發(fā)時再根據(jù)eventType從subscriptionsByEventType中獲取訂閱方法進(jìn)行分發(fā)(后面post中會分析)
2创夜、typesBySubscriber通過注冊對象保存該注冊對象所有的事件杭跪;這里保存代表為實(shí)際注冊,待解注冊時驰吓,再講該注冊對象的eventType從typesBySubscriber中移除涧尿,這個在unregister中可以體現(xiàn)
(2) unregister
接下來我們就來看看unregister方法:
/** Unregisters the given subscriber from all event classes. */
public synchronized void unregister(Object subscriber) {
//1、獲取緩存中注冊對象所有事件類型檬贰,遍歷并解訂閱事件
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
//全部事件解訂閱后姑廉,刪除typesBySubscriber中的類對象,實(shí)際這里表示解注冊
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
分析代碼可以知道翁涤,解注冊實(shí)際做了兩件事
1桥言、解訂閱所有的訂閱事件,及遍歷執(zhí)行unsubscribeByEventType()方法
2萌踱、訂閱類移除map列表中,即typesBySubscriber.remove(subscriber)
unsubscribeByEventType()方法通過名稱已經(jīng)很明顯;無非就是將注冊時保存在subscriptionsByEventType中的訂閱方法移除号阿;具體代碼貼出并鸵,但并沒有太值得閱讀的地方
/** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
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--;
}
}
}
}
3.post方法
剛剛已經(jīng)分析register方法,發(fā)現(xiàn)register其實(shí)最主要的就是將所有已注冊對象中的訂閱方法保存在subscriptionsByEventType這個map中扔涧,那post自然就是遍歷subscriptionsByEventType這個map然后執(zhí)行對應(yīng)的分發(fā)园担。
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
/** Posts the given event to the event bus. */
public void post(Object event) {
//1、使用ThreadLocal獲取當(dāng)前線程參數(shù)
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
//將事件加入List隊(duì)列中
eventQueue.add(event);
//2枯夜、判斷當(dāng)前線程post狀態(tài)
if (!postingState.isPosting) {
postingState.isMainThread = isMainThread();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
//3弯汰、postSingleEvent處理單個事件
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
//4、恢復(fù)post線程狀態(tài)
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
這段代碼主要是判斷當(dāng)前線程post狀態(tài)湖雹,如果有正在分發(fā)中的事件咏闪,則將新事件置入事件池排隊(duì)等待執(zhí)行;如果沒有劝枣,則將事件加入隊(duì)列并執(zhí)行汤踏。其核心代碼為postSingleEvent(eventQueue.remove(0), postingState) 所以我們繼續(xù)看看postSingleEvent做了些什么事
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;//該屬性判斷是否存在待分發(fā)事件的訂閱方法
if (eventInheritance) {//eventInheritance為默認(rèn)Builder中的值,默認(rèn)為true
//找到當(dāng)前待分發(fā)事件的所有事件類型(這里包括父類舔腾、接口類等)
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
//1溪胶、postSingleEventForEventType通過事件類型查找是否有對應(yīng)的訂閱方法
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
//2、如果沒有找到對應(yīng)的訂閱方法稳诚,發(fā)送一個默認(rèn)事件
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));
}
}
}
1哗脖、判斷是否找到待分發(fā)事件的訂閱方法,找到則分發(fā)事件扳还,其核心代碼為subscriptionFound |= postSingleEventForEventType(event, postingState, clazz)
2才避、未找到則默認(rèn)發(fā)送一個默認(rèn)的事件,post(new NoSubscriberEvent(this, event))
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//1氨距、在subscriptionsByEventType中獲取該事件對應(yīng)訂閱方法的集合
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
//2桑逝、遍歷集合,并執(zhí)行分發(fā)事件至具體的已訂閱方法中
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
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;
}
這里的主要邏輯如下
1俏让、通過事件類對象在subscriptionsByEventType這個map中取出該事件的所有訂閱類集合楞遏,subscriptionsByEventType中的訂閱方法集合是在注冊是添加的,我們在分析register源碼時已經(jīng)分析了首昔;
2寡喝、取出該事件訂閱方法合集之后就是遍歷所有的訂閱方法并分發(fā),該過程核心代碼為:postToSubscription(subscription, event, postingState.isMainThread)
說了那么久才真正的進(jìn)入post最核心的地方--事件分發(fā)勒奇,到目前為止我們知道post進(jìn)入時會根據(jù)當(dāng)前線程獲取一個緩存信息類postingState對象预鬓,其不同線程有通的隊(duì)列處理消息分發(fā);但是我們都知道EventBus中是幫我們做了線程切換的赊颠,我們可以通過@ Subscribe注解的threadMode屬性指定訂閱方法執(zhí)行的線程格二;那這一塊的具體邏輯應(yīng)該就是在postToSubscription中劈彪,所以帶著問題我們一起進(jìn)入看看:
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 MAIN_ORDERED:
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) {
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);
}
}
進(jìn)入就可以看到代碼對threadMode進(jìn)行判斷:
PSOTING:直接反射調(diào)用訂閱方法;該模式表示在哪個線程發(fā)布事件就在哪個線程處理
MAIN:如果當(dāng)前post線程為主線程直接反射調(diào)用方法(防止主線程阻塞)蟋定,如果post線程不是主線程粉臊,則調(diào)用mainThreadPoster排隊(duì)處理;該模式表示在主線程調(diào)用訂閱方法
MAIN_ORDERED:因?yàn)閙ainThreadPoster不會為null所以一直會排隊(duì)處理驶兜,并且會回調(diào)到主線程處理扼仲;該模式表示在主線程中排隊(duì)處理(即等待上一個時間處理后再發(fā)送下一個事件)
BACKGROUND:如果當(dāng)前post線程為主線程,開啟一個新的后臺線程處理分發(fā)抄淑,如果當(dāng)前post線程不為主線程屠凶,則直接反射調(diào)用;該模式表示事件一直在后臺線程中處理
ASYNC:由asyncPoster排隊(duì)處理肆资;該模式表示不管post線程是否為主線程矗愧,都會新開一個異步線程處理
這邊可以總結(jié)得出,部分情況直接反射調(diào)用訂閱方法郑原;部分根據(jù)情況開啟對應(yīng)的線程處理唉韭;如mainThreadPoster實(shí)際是Handler子類,通過handler機(jī)制切換回主線程犯犁,backgroundPoster属愤、asyncPoster實(shí)際實(shí)現(xiàn)了Runable接口,在子線程中執(zhí)行酸役;他們主要的工作只是線程切換住诸,切換后最終都會通過EventBus的反射方法地調(diào)用訂閱方法 eventBus.invokeSubscriber(pendingPost)
反射方法如下:
其中帶一個入?yún)⒌姆瓷浞椒ň褪枪┚€程切換后調(diào)用的反射方法
/**
* Invokes the subscriber if the subscriptions is still active. Skipping subscriptions prevents race conditions
* between {@link #unregister(Object)} and event delivery. Otherwise the event might be delivered after the
* subscriber unregistered. This is particularly important for main thread delivery and registrations bound to the
* live cycle of an Activity or Fragment.
*/
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
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);
}
}
至此我們的源碼分析就結(jié)束了,現(xiàn)在讓我們回到開始的那幾個問題
1涣澡、EventBus是如何確定哪些方法是訂閱方法的
答:通過源碼分析知道贱呐,EventBus注冊是傳入一個類對象,然后對類對象的所有方法(包括其父類的所有方法)進(jìn)行遍歷入桂,然后根據(jù)一定的規(guī)則過濾訂閱方法奄薇,分析過程中已列出,可以重新查看SubscriberMethodFinder類中的findUsingReflectionInSingleClass()方法抗愁;
2惕艳、EventBus是如何做線程切換的
答:通過Handler由子線程切換到主線程;通過實(shí)現(xiàn)Runable接口驹愚,切換至子線程處理,線程切換后通過反射調(diào)用訂閱方法分發(fā)事件
3劣纲、EventBus為什么不支持跨進(jìn)程
答:咋一看我們好像沒有再源碼中分析這一問題逢捺,其實(shí)這是一個需要理解的問題;首先我們需要理解Android的沙箱隔離機(jī)制癞季,Android中為了各應(yīng)用的安全劫瞳,不允許應(yīng)用直接訪問其他應(yīng)用倘潜,所以Android中應(yīng)用通訊就需要另一個技術(shù)實(shí)現(xiàn)--IPC跨進(jìn)程通訊,我們回想下EventBus注冊時保存的訂閱方法的map集合志于,是保存在內(nèi)存中的涮因,我們Post發(fā)送事件時也是直接在內(nèi)存中取出map中的方法,整個過程數(shù)據(jù)都涉及任何的IPC通訊伺绽。所以自然無法做到跨進(jìn)程調(diào)用