otto源碼分析,otto源碼
otto這個開源項目是一個event bus模式的訊息架構,用於程式各個模組之間的通訊,此訊息架構可以使得各個
模組之間減少耦合性。
此項目是支付公司square一個開源項目,項目託管於github
https://github.com/square/otto
基本模型是,Android的組件可以註冊監聽,然後發送訊息,接收訊息,模式就是觀察者模式,但是有別於
java實現的觀察者模式,otto更具解耦性,通過註解可以現實監聽工作。
otto中的總控制中心的類是Bus,複雜事件的註冊分發工作。
首先要把需要把監聽事件的組件或者發送事件的組件註冊進去
調用Bus的register方法
publicvoidregister(Object object)
這個方法的解釋是這樣的,先看下英文
/** * Registers all handler methods on {@code object} to receive events and producer methods to provide events. * If any subscribers are registering for types which already have a producer they will be called immediately * with the result of calling that producer. * If any producers are registering for types which already have subscribers, each subscriber will be called with * the value from the result of calling the producer. * * @param object object whose handler methods should be registered. * @throws NullPointerException if the object is null. */
參數這個對象的所有的事件處理方法(訂閱者法)用於處理接受到的事件,生產者方法用於提供事件。
意思是說,這個註冊者即可以接收事件,也可以生產事件。
接著說了註冊時的一些特殊情況,
(1)如果在註冊的時候,訂閱了一個事件類型,並且有產生事件的方法,那麼會立即調用產生事件的方法,
把事件分發給這個訂閱者方法。
(2)如果在註冊的時候,產生特定事件的方法已經存在了訂閱者,會呼叫事件產生方法,把事件分發給事件
訂閱者。
方法的具體實現分析:
public void register(Object object) { if (object == null) { throw new NullPointerException("Object to register must not be null."); } //檢查是否在主線程中進行了註冊的,預設必須在主線程中調用 enforcer.enforce(this); //key是事件的class對象 Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
上面的代碼用於擷取這個被註冊對象的所有生產者方法,可以對應於多個事件的生產者方法
一個被註冊對象,同一個事件只能註冊一個生產者方法。
handlerFinder是HandlerFinder的執行個體,是Bus的輔助類,用於找到指定被註冊者的所有生產者和訂閱者方法。
handlerFinder.findAllProducers(object)返回一個map集合,key是事件的Class的執行個體,value
是EventProducer是對生產者方法和被註冊者執行個體的封裝。
從這裡可以看出,雖然沒有繼續看這個方法的代碼,可以猜測被註冊者對於同一個事件只能有一個生產者。
我們繼續跟蹤HandlerFinder findAllProducers()方法的代碼
HandlerFinder只是一個借口,然後在其內部實現了一個內部類
如下:
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); } };
會調用到這句代碼:
AnnotatedHandlerFinder.findAllProducers(listener)
進去看下代碼
static Map<Class<?>, EventProducer> findAllProducers(Object listener) { final Class<?> listenerClass = listener.getClass(); Map<Class<?>, EventProducer> handlersInMethod = new HashMap<Class<?>, EventProducer>(); //檢查是否不存在此listenerClass的生產者方法,需要找出來放到PRODUCERS_CACHE中 //PRODUCERS_CACHE是一個map,可以是listener的class對象,值是所有的事件生產者方法 if (!PRODUCERS_CACHE.containsKey(listenerClass)) { loadAnnotatedMethods(listenerClass); }//下面的代碼就是把所有的生產者方法封裝起來,返回給調用者 Map<Class<?>, Method> methods = PRODUCERS_CACHE.get(listenerClass); if (!methods.isEmpty()) { for (Map.Entry<Class<?>, Method> e : methods.entrySet()) { EventProducer producer = new EventProducer(listener, e.getValue()); handlersInMethod.put(e.getKey(), producer); } } return handlersInMethod; }
我們再回到Bus的register方法
//key是事件的class對象 Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object); for (Class<?> type : foundProducers.keySet()) { //下面幾行代碼用來檢查,事件是否已經註冊過了,一個類一個事件只能註冊一次 final EventProducer producer = foundProducers.get(type); EventProducer previousProducer = producersByType.putIfAbsent(type, producer); //checking if the previous producer existed if (previousProducer != null) { throw new IllegalArgumentException("Producer method for type " + type + " found on type " + producer.target.getClass() + ", but already registered by type " + previousProducer.target.getClass() + "."); } //檢查一下註冊這個事件的註冊者是否存在,存在就回調一下註冊者 Set<EventHandler> handlers = handlersByType.get(type); if (handlers != null && !handlers.isEmpty()) { for (EventHandler handler : handlers) { dispatchProducerResultToHandler(handler, producer); } } }這行代碼用於回調
dispatchProducerResultToHandler(handler, producer);
具體實現就是通過反射去調用producer生產出方事件,把事件傳遞給handler,再通過反射
回調註冊的方法。
繼續。。。
//如果有處理此事件的註冊者,回調註冊者 Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object); for (Class<?> type : foundHandlersMap.keySet()) { //type變數是事件的class對象 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); handlers.addAll(foundHandlers); }
regeister這個方法解釋完了。
在繼續看下post(event)方法
這個方法的作用是分發事件到所有註冊這個事件的方法
有可能這個事件分發失敗,會封裝一個DeadEvent對象,然後重新分發,但是這個DeadEvent對象沒有被處理。。。
public void post(Object event) { if (event == null) { throw new NullPointerException("Event to post must not be null."); } enforcer.enforce(this); //返回這個event的所有繼承關係鏈的所有class對象(父類class對象和自己) Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass()); //對event家族的所有類的相關註冊方法進行調用 boolean dispatched = false; for (Class<?> eventType : dispatchTypes) { //獲得和eventType相關的所有註冊方法 Set<EventHandler> wrappers = getHandlersForEventType(eventType); //把需要回調處理的註冊方法的封裝類塞進當前線程處理的隊列中去 if (wrappers != null && !wrappers.isEmpty()) { dispatched = true; for (EventHandler wrapper : wrappers) { enqueueEvent(event, wrapper); } } } //沒處理的,再分發一次,但是沒有發現再次處理的邏輯 if (!dispatched && !(event instanceof DeadEvent)) { post(new DeadEvent(this, event)); } dispatchQueuedEvents(); }
接下來就是登出方法unregister(listener)
刪除和這個listener對象相關的生產事件的方法和註冊監聽的方法
public void unregister(Object object) { if (object == null) { throw new NullPointerException("Object to unregister must not be null."); } enforcer.enforce(this); Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object); for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) { final Class<?> key = entry.getKey(); EventProducer producer = getProducerForEventType(key); EventProducer value = entry.getValue(); if (value == null || !value.equals(producer)) { throw new IllegalArgumentException( "Missing event producer for an annotated method. Is " + object.getClass() + " registered?"); } producersByType.remove(key).invalidate(); } //返回當前對象的所有註冊的方法,置為無效並刪除掉 Map<Class<?>, Set<EventHandler>> handlersInListener = handlerFinder.findAllSubscribers(object); for (Map.Entry<Class<?>, Set<EventHandler>> entry : handlersInListener.entrySet()) { //返回對應event的所有註冊方法的封裝類 Set<EventHandler> currentHandlers = getHandlersForEventType(entry.getKey()); Collection<EventHandler> eventMethodsInListener = entry.getValue(); if (currentHandlers == null || !currentHandlers.containsAll(eventMethodsInListener)) { throw new IllegalArgumentException( "Missing event handler for an annotated method. Is " + object.getClass() + " registered?"); } for (EventHandler handler : currentHandlers) { if (eventMethodsInListener.contains(handler)) { handler.invalidate(); } } currentHandlers.removeAll(eventMethodsInListener); } }最後總結一下,
(1)同一個事件只能有一個生產此事件的方法,如果存在多個會報非檢查異常,產生此類事件的只允許有一個來源或者說只允許
有一個活者的來源。
(2)同一個事件可以有多個註冊監聽同一個事件的方法,只要存在就會分發給他們。
(3)按照官方的demo盡量只有一個Bus執行個體,一是減少記憶體消耗,也利於分發工作,如果不同的Bus,那麼就無法把分發給其他Bus的註冊監聽的方法了。
這個EventBus訊息架構比較適合推送的處理中心對訊息的分發工作,可以解耦的方式,分發給程式的各個模組。
square公司還有很多比較好的開源項目,
網路程式庫okhttp初支援http外,還支援spdy,github地址
https://github.com/square/okhttp;
處理圖片的庫picasso(畢加索) ,github地址
https://github.com/square/picasso;
一個日曆控制項陳列庫,包含Android版和iOS版, github地址
https://github.com/square/android-times-square (Android版)。
其它square公司的開源項目:
https://github.com/square
怎分析網站原始碼
這個看網頁的難易,互動式網頁的話(如用ASP編的)你就的熟悉程式設計語言,如果是CSS編寫的話,就得熟悉CSS。至於一些糅合製作的網頁就是高難度了 ,我也不是太精
c++ 源碼 分析?
這麼說,你一定有c++的基礎了,那麼我推薦一本書給你
侯俊傑的 《slt源碼分析》。stl不用說,那可是精品,都作為標準了。
這本書是很好,但是要求基本也比較高的。
不知道誰說過一句話:什麼樣的書固然沒什麼用處,但是對於特別的人,特別的時間,將會特別的有用!
還有源碼好多了,你可以看一下一些c++的論壇上面會後好多代碼的,但是品質不值得保證!
個人認為既然是想提高水平,就要看一些精品。不管起點要求多高,因為這條路終究要走下去的!!
僅是建議!