【Android翻譯】組件通訊模式

##目標:避免緊耦合java

本文對原文進行了精簡git

原文連接:Communication patterns for application componentsgithub

##緊耦合 組件之間相互持有引用,以及直接調用方法.在下面的代碼中,MenuFragment持有MagazineActivity的直接引用,所以, MenuFragment 就與 MagazineActivity緊耦合了. 一旦沒有了MagazineActivity,就沒法工做了.數據結構

// 緊耦合示例

class MenuFragment extends Fragment {
    private void onArticleClick(int articleId) {
        MagazineActivity magAct = (MagazineActivity) getActivity();
        magAct.showArticle(articleId);
    }
}

在這樣的設計中,一個類的修改可能會影響到一大波相關的類,若是開發中還涉及到多個開發人員,那麼這種狀況帶來的只會是痛苦和悲哀..app

鬆耦合的核心就是一種減小組件之間的依賴關係,一個鬆耦合系統能夠很方便的分解爲良構的元素.這樣就使得系統更具備彈性與擴展性. 每一個開發人員能夠維護一個單獨的模塊,並使用標準的協議與其餘部分通訊.工具

##常規解耦方式:接口 (我的補充:接口並非單純指代的java裏面的interface關鍵字,而是指的一種消息規範/協議) 接口是一個強大的解耦工具:類能夠經過接口進行通訊,而沒必要要直接引用另外一個具體類.一個類能夠向外提供一個接口供其餘類與之通訊.在這個抽象層上,其餘類不用關心具體的實現是什麼.優化

//接口示例

class MenuFragment extends Fragment {
    public static MenuFragment instantiate(ArticleSwitcher articleSwitcher) {
        MenuFragment menuFragment = new MenuFragment();
        menuFragment.articleSwitcher = articleSwitcher;
        return menuFragment;
    }

    ArticleSwitcher articleSwitcher;

    public void onArticleClick(int articleId) {
	    articleSwitcher.showArticle(articleId);
    }
}

使用接口的缺點:this

  1. 組件之間仍是須要相互瞭解以傳遞接口,部分依賴依舊存在
  2. 接口不能經過intent傳遞
  3. 在大項目中,接口數量會急劇增長,致使大量的模板代碼
  4. 當接口在組件之間傳遞時會造成接口鏈,致使複雜度上升

##優雅解決方案:消息總線線程

基於發佈/訂閱者模式的通訊方案.發佈者發佈一個通知,訂閱者獲得通知並作出反應,所以,發佈者和訂閱者之間就實現瞭解耦.設計

###實現消息總線

####隱式intent + BroadcastReceiver

經過隱式Intent的通訊能夠看做是消息隊列的一種形式: sendBroadcast(Intent) 或者 startActivity(Intent)是發佈者方法,含有相應IntentFilter的BroadcastReceiver 或者 Activity則扮演訂閱者的角色.

優勢與缺點

優勢:能夠跨應用傳遞,也是Android裏面的標準方法

缺點:沒法傳遞複雜數據,必須經過bundle來傳遞

FluffyEvents 就是一個經過 BroadcastReceiver 實現的消息總線.

EventBus: 基於事件的消息總線

("事件"自己也是一種消息,原理仍是訂閱/發佈者模式)

事件自己能夠是任何java類,以下:

// 一個示例事件類

class DownloadProgressEvent {
    private float progress;
    public DownloadProgressEvent(float progress) {
        this.progress = progress;
    }

    public float getProgress() {
        return progress;
    }
}

#####EventBus: 大體原理

EventBus使用合適的數據結構來維持事件以及訂閱者的對應關係,好比Otto使用的方式:

/** Cache event bus subscriber methods for each class. */
private static final Map<Class<?>, Map<EventClass, Set>> SUBSCRIBERS_CACHE = new HashMap<Class<?>, Map<EventClass, Set>>();

每當有訂閱者註冊或者註銷的時候,都會同時更新相應的對應關係,一般,Activity 或者 Fragment會在onResume階段進行註冊,在onPause階段進行註銷.(譯者注:能夠減小內存泄露的問題)

每當有事件發佈的時候,EventBus遍歷整個對應關係,找到全部符合條件的訂閱者方法並執行.

#####Sticky Event

相似Android原生的StickyBroadcast,使得一個訂閱者在任什麼時候候註冊均可以得到這個事件.

##總結

因爲EventBus並非Android的內在機制,所以沒法跨應用傳遞事件.

比較經常使用的兩個EventBus開源類庫:

Square’s Otto:基於註解,在Guava EventBus基礎上針對Android平臺進行了優化

GreenRobot’s EventBus:更好的線程分發機制.

(譯者注: EventBus比較適合組件之間的解耦, 而接口是一個更抽象的概念,還能夠用在view或者其餘方面)

####Android分享 Q羣:315658668

相關文章
相關標籤/搜索