平時一直使用EventBus這個元件,真的挺好用的,最近使用的時候偶爾出現錯誤就找了一下資料。
以下内容為轉載,記錄下來以後記不清楚了可以再回顧一下
EvenBus簡化了應用程式内各元件間、元件與背景線程間的通信。比如請求網絡,等網絡傳回時通過Handler或Broadcast通知UI,兩個Fragment之間需要通過Listener通信,這些需求都可以通過EventBus實作。它的效果和Handler的效果大緻相同,但是實作原理和使用方法是完全不同的,它是基于儲存相應方法,然後通過反射機制來實作的。更多的使用和原理,請參考:[Android EventBus實戰](http://blog.csdn.net/jdsjlzx/article/details/40856535) 和[EventBus使用詳解(二)——EventBus使用進階](http://blog.csdn.net/harvic880925/article/details/40787203) ,他們會教會你怎樣去使用EventBus,網上還有更多的教程,可以去搜尋學習。
它是一個開源架構,可以在github上下載下傳到:
https://github.com/greenrobot/EventBus
下載下傳來後它的目錄結構如下:

我們要使用EventBus隻需将EventBus這個檔案夾拷貝到我們的項目中,這樣在我們的工程中就會出現兩個包:
最後是我在第一次使用時出現的一個異常,或許初學者也會遇到的異常:
Subscriber ****has no public methods called
我們分析下為什麼?
我這裡先給出原因,個那些急忙解決的人:是因為在我們的類裡使用了EventBus.getDefualt().register(this)了,但是在這個類裡卻沒有定義一個以onEvent開頭的、非靜态的、public權限以及僅僅隻有一個參數 的方法,也就是沒有類似于:public void onEvent**(Object arg)這樣的方法,導緻出現了這個錯誤。
想要徹底知道為什麼,請先檢視EventBus的實作原理: Android EventBus源碼解析 帶你深入了解EventBus(http://blog.csdn.net/lmj623565791/article/details/40920453) 。
看完了這篇文章,你将會知道EventBus的實作原理,那麼我們就再來看看這個異常發生的原因:
在de.greenrobot.event.SubscriberMethodFinder類裡findSubscriberMethods()的方法,是在調用EventBus.getDefualt().register(this)後,經過層層調用,最後會調用到這個方法,
看源碼:
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
...
//擷取clazz這個類的所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
String methodName = method.getName();
if (methodName.startsWith(ON_EVENT_METHOD_NAME)) {
int modifiers = method.getModifiers();
//public的非靜态的方法
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
//隻有一個參數
if (parameterTypes.length == 1) {
String modifierString = methodName.substring(ON_EVENT_METHOD_NAME.length());
ThreadMode threadMode;
if (modifierString.length() == 0) {
threadMode = ThreadMode.PostThread;
} else if (modifierString.equals("MainThread")) {
threadMode = ThreadMode.MainThread;
} else if (modifierString.equals("BackgroundThread")) {
threadMode = ThreadMode.BackgroundThread;
} else if (modifierString.equals("Async")) {
threadMode = ThreadMode.Async;
} else {
if (skipMethodVerificationForClasses.containsKey(clazz)) {
continue;
} else {
throw new EventBusException("Illegal onEvent method, check for typos: " + method);
}
}
Class<?> eventType = parameterTypes[0];
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(methodName);
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
if (eventTypesFound.add(methodKey)) {
// Only add if not already found in a sub class
subscriberMethods.add(new SubscriberMethod(method, threadMode, eventType));
}
}
} else if (!skipMethodVerificationForClasses.containsKey(clazz)) {
Log.d(EventBus.TAG, "Skipping method (not public, static or abstract): " + clazz + "."
+ methodName);
}
}
}
clazz = clazz.getSuperclass();
}
//到此為查找目标對象(regiter(this)的this對象)中 onEvent開頭的、非靜态的、public權限以及僅僅隻有一個參數 的方法,然後将這些方法放入到subscriberMethods中
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called "
+ ON_EVENT_METHOD_NAME);
}
//看到沒有,這就是這個異常抛出的地方,就是判斷subscriberMethods如果是null,就抛出這個異常。
....
}
好了,這個異常我們就分析到此,希望童鞋們能夠很好的查找錯誤,分析錯誤,更好的去避免。通過源碼是一個很好的方時。