說明:本文的解析過程並不只是簡單的講解框架中各個方法的調用邏輯、程序的執行過程,而是依賴於示例代碼,結合了具體的的示例程序的執行流程,有助於更好的理解。
有關Otto的使用方法參見另一篇文章: Android事件總線框架Otto使用介紹
package com.example.myotto;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private Button mBtnJumpToPost, mBtnJumpToProduce, mBtnJumpToMainActivity;
private TextView mTvMessage, mTvMessageUpdate;
public static void start(Context context) {
context.startActivity(new Intent(context, MainActivity.class));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTvMessage = (TextView) this.findViewById(R.id.tv_message);
mTvMessageUpdate = (TextView) this.findViewById(R.id.tv_message_update);
mBtnJumpToPost = (Button) this.findViewById(R.id.btn_jump_to_post);
mBtnJumpToMainActivity = (Button) this.findViewById(R.id.btn_jump_to_main_activity);
mBtnJumpToProduce = (Button) this.findViewById(R.id.btn_jump_to_produce);
mBtnJumpToPost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PostActivity.start(MainActivity.this);
}
});
mBtnJumpToProduce.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ProduceActivity.start(MainActivity.this);
}
});
mBtnJumpToMainActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MainActivity.start(MainActivity.this);
}
});
Log.i(TAG, "method:onCreate#this#hashCode=" + this.hashCode());
OttoBus.getInstance().register(this);
}
@Subscribe
public void refreshMessage(EventData eventData) {
Log.i(TAG, "method:Subscribe#refreshMessage#eventData#hashCode=" + eventData.hashCode());
Log.i(TAG, "method:Subscribe#refreshMessage#eventData=" + eventData);
mTvMessage.setText(eventData.getUserName() + ":\n\n" + eventData.getMessage());
}
@Subscribe
public void updateMessage(EventData eventData) {
Log.i(TAG, "method:updateMessage#updateMessage#eventData#hashCode=" + eventData.hashCode());
Log.i(TAG, "method:Subscribe#updateMessage#eventData=" + eventData);
mTvMessageUpdate.setText(eventData.getUserName() + ":\n\n" + eventData.getMessage());
}
@Override
protected void onDestroy() {
super.onDestroy();
OttoBus.getInstance().unregister(this);
}
}
Bus的構造過程:
Otto源碼中並沒有提供Bus的單例實現,我們可以在使用前自行構造一個單例模式。
package com.example.myotto;
import com.squareup.otto.Bus;
public class OttoBus extends Bus {
private volatile static OttoBus bus;
private OttoBus() {
}
public static OttoBus getInstance() {
if (bus == null) {
synchronized (OttoBus.class) {
if (bus == null) {
bus = new OttoBus();
}
}
}
return bus;
}
}
在源碼中Bus類的無參構造方法,實際上最終還是調用了 Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder)這個構造方法,並且在調用過程中注入了一些默認的參數 :DEFAULT_IDENTIFIER 、 ThreadEnforcer.MAIN 和HandlerFinder.ANNOTATED。
public class Bus {
public static final String DEFAULT_IDENTIFIER = "default";
/** All registered event handlers, indexed by event type. */
private final ConcurrentMap<Class<?>, Set<EventHandler>> handlersByType =
new ConcurrentHashMap<Class<?>, Set<EventHandler>>();
/** All registered event producers, index by event type. */
private final ConcurrentMap<Class<?>, EventProducer> producersByType =
new ConcurrentHashMap<Class<?>, EventProducer>();
/** Identifier used to differentiate the event bus instance. */
private final String identifier;
/** Thread enforcer for register, unregister, and posting events. */
private final ThreadEnforcer enforcer;
/** Used to find handler methods in register and unregister. */
private final HandlerFinder handlerFinder;
/** Queues of events for the current thread to dispatch. */
private final ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>> eventsToDispatch =
new ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>>() {
@Override protected ConcurrentLinkedQueue<EventWithHandler> initialValue() {
return new ConcurrentLinkedQueue<EventWithHandler>();
}
};
/** True if the current thread is currently dispatching an event. */
private final ThreadLocal<Boolean> isDispatching = new ThreadLocal<Boolean>() {
@Override protected Boolean initialValue() {
return false;
}
};
public Bus() {
this(DEFAULT_IDENTIFIER);
}
public Bus(String identifier) {
this(ThreadEnforcer.MAIN, identifier);
}
public Bus(ThreadEnforcer enforcer) {
this(enforcer, DEFAULT_IDENTIFIER);
}
public Bus(ThreadEnforcer enforcer, String identifier) {
this(enforcer, identifier, HandlerFinder.ANNOTATED);
}
Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder) {
this.enforcer = enforcer;
this.identifier = identifier;
this.handlerFinder = handlerFinder;
}
.......省略.......
}
根據具體的示例分析 Bus 的 register(Object object) 方法在MainActivity的執行過程:
public class Bus{
.......省略.......
public void register(Object object) {
if (object == null) {
throw new NullPointerException("Object to register must not be null.");
}
// 檢查線程,如果不是對應的線程則拋異常;默認的構造方法裏使用的是主線程;
// enforcer 就是構造過程中注入的默認參數 ThreadEnforcer.MAIN;
// 它是 ThreadEnforcer 的一個實例,實現的 enforce(Bus bus)方法裏會進行線程檢查
enforcer.enforce(this); // 1
// handlerFinder 就是構造過程中注入的默認參數 HandlerFinder.ANNOTATED;
// 它是 HandlerFinder 的一個實例,實現了兩個方法:findAllProducers(Object listener) 和 findAllSubscribers(Object listener);
// findAllProducers(Object listener) 內部調用了 AnnotatedHandlerFinder 的 findAllProducers(Object listener);
// 因爲 MainActivity 中並沒有 @Produce 的註解方法,所以這裏返回的map大小是0,相關的邏輯也不再執行,接下來程序就會執行 handlerFinder.findAllSubscribers(object)方法;
Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object); // 2
.......省略.......
// handlerFinder 就是構造過程中注入的默認參數 HandlerFinder.ANNOTATED;
// findAllSubscribers(Object listener) 內部調用了 AnnotatedHandlerFinder 的 findAllSubscribers(Object listener);
// 這裏返回的map是;
Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object); // 3
for (Class<?> type : foundHandlersMap.keySet()) {
Set<EventHandler> handlers = handlersByType.get(type);
if (handlers == null) {
//concurrent put if absent
Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();
handlers = handlersByType.putIfAbsent(type, handlersCreation);
if (handlers == null) {
handlers = handlersCreation;
}
}
final Set<EventHandler> foundHandlers = foundHandlersMap.get(type);
if (!handlers.addAll(foundHandlers)) {
throw new IllegalArgumentException("Object already registered.");
}
}
for (Map.Entry<Class<?>, Set<EventHandler>> entry : foundHandlersMap.entrySet()) {
Class<?> type = entry.getKey();
EventProducer producer = producersByType.get(type);
if (producer != null && producer.isValid()) {
Set<EventHandler> foundHandlers = entry.getValue();
for (EventHandler foundHandler : foundHandlers) {
if (!producer.isValid()) {
break;
}
if (foundHandler.isValid()) {
dispatchProducerResultToHandler(foundHandler, producer);
}
}
}
}
}
.......省略.......
}
標註1處,即ThreadEnforcer類的處理邏輯:
public interface ThreadEnforcer {
void enforce(Bus bus);
ThreadEnforcer ANY = new ThreadEnforcer() {
@Override public void enforce(Bus bus) {
// Allow any thread.
}
};
ThreadEnforcer MAIN = new ThreadEnforcer() {
@Override public void enforce(Bus bus) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("Event bus " + bus + " accessed from non-main thread " + Looper.myLooper());
}
}
};
}
HandlerFinder類的具體處理邏輯:
interface HandlerFinder {
Map<Class<?>, EventProducer> findAllProducers(Object listener);
Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener);
HandlerFinder ANNOTATED = new HandlerFinder() {
@Override
public Map<Class<?>, EventProducer> findAllProducers(Object listener) {
return AnnotatedHandlerFinder.findAllProducers(listener);
}
@Override
public Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {
return AnnotatedHandlerFinder.findAllSubscribers(listener);
}
};
}
標註2處具體調用的方法:
final class AnnotatedHandlerFinder {
/** Cache event bus producer methods for each class. */
private static final ConcurrentMap<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE =
new ConcurrentHashMap<Class<?>, Map<Class<?>, Method>>();
/** Cache event bus subscriber methods for each class. */
private static final ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE =
new ConcurrentHashMap<Class<?>, Map<Class<?>, Set<Method>>>();
.......省略..........
/** This implementation finds all methods marked with a {@link Produce} annotation. */
static Map<Class<?>, EventProducer> findAllProducers(Object listener) {
// listener 就是示例代碼中的 MainActivity 的實例對象
//
final Class<?> listenerClass = listener.getClass();
Map<Class<?>, EventProducer> handlersInMethod = new HashMap<Class<?>, EventProducer>();
// 此時緩存中還沒有,methods集合爲null;
Map<Class<?>, Method> methods = PRODUCERS_CACHE.get(listenerClass);
if (null == methods) {
methods = new HashMap<Class<?>, Method>();
loadAnnotatedProducerMethods(listenerClass, methods);
}
// 因爲當前MainActivity裏只有Subject註解的方法,所在這個集合大小是0;
if (!methods.isEmpty()) {
for (Map.Entry<Class<?>, Method> e : methods.entrySet()) {
EventProducer producer = new EventProducer(listener, e.getValue());
handlersInMethod.put(e.getKey(), producer);
}
}
// 當前這個返回結果集合大小是0;
return handlersInMethod;
}
.......省略..........
}
loadAnnotatedProducerMethods(Class<?> listenerClass, Map<Class<?>, Method> producerMethods) 方法,最終調用loadAnnotatedMethods(Class<?> listenerClass,
Map<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods) 這個方法
.......省略.........
private static void loadAnnotatedProducerMethods(Class<?> listenerClass,
Map<Class<?>, Method> producerMethods) {
Map<Class<?>, Set<Method>> subscriberMethods = new HashMap<Class<?>, Set<Method>>();
loadAnnotatedMethods(listenerClass, producerMethods, subscriberMethods);
}
/**
* Load all methods annotated with {@link Produce} or {@link Subscribe} into their respective caches for the
* specified class.
*/
private static void loadAnnotatedMethods(Class<?> listenerClass,
Map<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods) { // 傳入的參數: 圖1
for (Method method : listenerClass.getDeclaredMethods()) {
// The compiler sometimes creates synthetic bridge methods as part of the
// type erasure process. As of JDK8 these methods now include the same
// annotations as the original declarations. They should be ignored for
// subscribe/produce.
// 如果橋接方法,則不處理
if (method.isBridge()) {
continue;
}
// 判斷方法是否以@Subscribe爲註解
if (method.isAnnotationPresent(Subscribe.class)) {
Class<?>[] parameterTypes = method.getParameterTypes();
// 方法的參數類型的數量只能有1個,否則拋出異常
if (parameterTypes.length != 1) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation but requires "
+ parameterTypes.length + " arguments. Methods must require a single argument.");
}
Class<?> eventType = parameterTypes[0];
if (eventType.isInterface()) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
+ " which is an interface. Subscription must be on a concrete class type.");
}
// 方法的訪問修飾符必須是public;
if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
+ " but is not 'public'.");
}
Set<Method> methods = subscriberMethods.get(eventType);
if (methods == null) {
methods = new HashSet<Method>();
subscriberMethods.put(eventType, methods);
}
methods.add(method);
// 判斷方法是否以@Produce爲註解
} else if (method.isAnnotationPresent(Produce.class)) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 0) {
throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires "
+ parameterTypes.length + " arguments. Methods must require zero arguments.");
}
// 方法的必須要有返回參數;
if (method.getReturnType() == Void.class) {
throw new IllegalArgumentException("Method " + method
+ " has a return type of void. Must declare a non-void type.");
}
Class<?> eventType = method.getReturnType();
if (eventType.isInterface()) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
+ " which is an interface. Producers must return a concrete class type.");
}
if (eventType.equals(Void.TYPE)) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation but has no return type.");
}
// 方法的訪問修飾符必須是public;
if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
+ " but is not 'public'.");
}
if (producerMethods.containsKey(eventType)) {
throw new IllegalArgumentException("Producer for type " + eventType + " has already been registered.");
}
producerMethods.put(eventType, method);
}
}
PRODUCERS_CACHE.put(listenerClass, producerMethods);
SUBSCRIBERS_CACHE.put(listenerClass, subscriberMethods);
}
.......省略.........
圖1:
當查找到第一個以 Subscribe 爲註解的 refreshMessage(EventData eventData)方法時,數據的處理流程:
1、判斷參數個數
2、判斷參數類型是否是接口類型
3、保存到對應的集合中
當查找到第二個以 Subscribe 爲註解的 updateMessage(EventData eventData)方法時,數據的處理流程:
查找完所有以 Subscribe 爲註解的方法後,再緩存入這個集合中:
總結一下上述方法中出現的集合存儲的數據類型:
Map<Class<?>, Set<Method>> subscriberMethods 集合存入的數據類型:
key 是 EventData 的Class對象
value 是Set<Method>集合,比如:refreshMessage(EventData eventData)方法 和 updateMessage(EventData eventData)方法;
ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE 集合存入的數據可以是:
key 是 MainActivity 的Class對象
value 是 subscriberMethods 集合;
標註3處最終調用的方法:
final class AnnotatedHandlerFinder {
/** Cache event bus producer methods for each class. */
private static final ConcurrentMap<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE =
new ConcurrentHashMap<Class<?>, Map<Class<?>, Method>>();
/** Cache event bus subscriber methods for each class. */
private static final ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE =
new ConcurrentHashMap<Class<?>, Map<Class<?>, Set<Method>>>();
.......省略..........
/** This implementation finds all methods marked with a {@link Subscribe} annotation. */
static Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {
Class<?> listenerClass = listener.getClass();
Map<Class<?>, Set<EventHandler>> handlersInMethod = new HashMap<Class<?>, Set<EventHandler>>();
// 此時緩存中已經有數據,如果沒有,最終還會調用上述的查找所有Subscribe註解的方法
Map<Class<?>, Set<Method>> methods = SUBSCRIBERS_CACHE.get(listenerClass);
if (null == methods) {
methods = new HashMap<Class<?>, Set<Method>>();
loadAnnotatedSubscriberMethods(listenerClass, methods);
}
if (!methods.isEmpty()) {
// 遍歷這個集合,將數據封裝到EventHandler的對象中,然後存入Map<Class<?>, Set<EventHandler>>集合中
for (Map.Entry<Class<?>, Set<Method>> e : methods.entrySet()) {
Set<EventHandler> handlers = new HashSet<EventHandler>();
for (Method m : e.getValue()) {
handlers.add(new EventHandler(listener, m));
}
handlersInMethod.put(e.getKey(), handlers);
}
}
return handlersInMethod;
}
.......省略..........
}
總結一下這段代碼執行完之後的數據情況:
循環遍歷了集合 Map<Class<?>, Set<Method>> subscriberMethods 集合存入的數據可以是:
key 是 EventData 的Class對象
value 是Set<Method>集合,比如:refreshMessage(EventData eventData)方法 和 updateMessage(EventData eventData)方法
找到每一個key下對應的Set<Method>集合,然後遍歷這個集合,將相應數據封裝到 EventHandler 對象中,並且存入Set<EventHandler > 集合中,裏層循環結束後,再將數據存入 Map<Class<?>, Set<EventHandler>> handlersInMethod 集合中;
EventHandler 對象創建時注入的參數 new EventHandler(listener, m);listener 是 MainActivity的Class對象,m 是 Subscribe註釋方法 refreshMessage(EventData eventData)方法;
Map<Class<?>, Set<EventHandler>> handlersInMethod 集合的 key 是 EventData 的Class對象,value 是 Set<EventHandler > 集合;
下面我們回到Bus裏標註3的返回結果:
public class Bus{
.......省略.......
public void register(Object object) {
.......省略.......
Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object); // 3
for (Class<?> type : foundHandlersMap.keySet()) {
// 此時handlersByType集合還是0,查找出的結果集合還是null;
Set<EventHandler> handlers = handlersByType.get(type);
if (handlers == null) {
//concurrent put if absent
Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();
// 此時key對應的value還不存在,此方法會添加key和value,並且返回null
handlers = handlersByType.putIfAbsent(type, handlersCreation);
if (handlers == null) {
// 將 CopyOnWriteArraySet類型的集合對象 handlersCreation 賦值給 handlers
handlers = handlersCreation;
}
}
final Set<EventHandler> foundHandlers = foundHandlersMap.get(type);
// 如果Set集合發生更改,則返回true。
if (!handlers.addAll(foundHandlers)) {
throw new IllegalArgumentException("Object already registered.");
}
}
.......省略.......
}
總結一下數據情況:
ConcurrentMap<Class<?>, Set<EventHandler>> handlersByType 的 key 是 EventData 的Class對象,value 是 Set<EventHandler > 集合;
到此註冊方法的執行流程已經完成。
由於作者水平有限,語言描述及代碼實現中難免有紕漏,望各位看官多提寶貴意見!
Hello , World !
感謝所有!