日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android组件化方案及组件消息总线modular-event实战

發(fā)布時(shí)間:2024/7/5 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android组件化方案及组件消息总线modular-event实战 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

背景

組件化作為Android客戶端技術(shù)的一個(gè)重要分支,近年來一直是業(yè)界積極探索和實(shí)踐的方向。美團(tuán)內(nèi)部各個(gè)Android開發(fā)團(tuán)隊(duì)也在嘗試和實(shí)踐不同的組件化方案,并且在組件化通信框架上也有很多高質(zhì)量的產(chǎn)出。最近,我們團(tuán)隊(duì)對(duì)美團(tuán)零售收銀和美團(tuán)輕收銀兩款A(yù)ndroid App進(jìn)行了組件化改造。本文主要介紹我們的組件化方案,希望對(duì)從事Android組件化開發(fā)的同學(xué)能有所啟發(fā)。

為什么要組件化

近年來,為什么這么多團(tuán)隊(duì)要進(jìn)行組件化實(shí)踐呢?組件化究竟能給我們的工程、代碼帶來什么好處?我們認(rèn)為組件化能夠帶來兩個(gè)最大的好處。

提高組件復(fù)用性

可能有些人會(huì)覺得,提高復(fù)用性很簡(jiǎn)單,直接把需要復(fù)用的代碼做成Android Module,打包AAR并上傳代碼倉(cāng)庫(kù),那么這部分功能就能被方便地引入和使用。但是我們覺得僅僅這樣是不夠的,上傳倉(cāng)庫(kù)的AAR庫(kù)是否方便被復(fù)用,需要組件化的規(guī)則來約束,這樣才能提高復(fù)用的便捷性。

降低組件間的耦合

我們需要通過組件化的規(guī)則把代碼拆分成不同的模塊,模塊要做到高內(nèi)聚、低耦合。模塊間也不能直接調(diào)用,這需要組件化通信框架的支持。降低了組件間的耦合性可以帶來兩點(diǎn)直接的好處:第一,代碼更便于維護(hù);第二,降低了模塊的Bug率。

組件化之前的狀態(tài)

我們的目標(biāo)是要對(duì)團(tuán)隊(duì)的兩款A(yù)pp(美團(tuán)零售收銀、美團(tuán)輕收銀)進(jìn)行組件化重構(gòu),那么這里先簡(jiǎn)單地介紹一下這兩款應(yīng)用的架構(gòu)。

總的來說,這兩款應(yīng)用的構(gòu)架比較相似,主工程Module依賴Business Module,Business Module是各種業(yè)務(wù)功能的集合,Business Module依賴Service Module,Service Module依賴Platform Module,Service Module和Platform Module都對(duì)上層提供服務(wù)。

有所不同的是Platform Module提供的服務(wù)更為基礎(chǔ),主要包括一些工具Utils和界面Widget,而Service Module提供各種功能服務(wù),如KNB、位置服務(wù)、網(wǎng)絡(luò)接口調(diào)用等。這樣的話,Business Module就變得非常臃腫和繁雜,各種業(yè)務(wù)模塊相互調(diào)用,耦合性很強(qiáng),改業(yè)務(wù)代碼時(shí)容易“牽一發(fā)而動(dòng)全身”,即使改一小塊業(yè)務(wù)代碼,可能要連帶修改很多相關(guān)的地方,不僅在代碼層面不利于進(jìn)行維護(hù),而且對(duì)一個(gè)業(yè)務(wù)的修改很容易造成其他業(yè)務(wù)產(chǎn)生Bug。

組件化方案調(diào)研

為了得到最適合我們業(yè)態(tài)和構(gòu)架的組件化方案,我們調(diào)研了業(yè)界開源的一些組件化方案和公司內(nèi)部其他團(tuán)隊(duì)的組件化方案,在此做個(gè)總結(jié)。

開源組件化方案調(diào)研

我們調(diào)研了業(yè)界一些主流的開源組件化方案。

  • CC

號(hào)稱業(yè)界首個(gè)支持漸進(jìn)式組件化改造的Android組件化開源框架。無論頁(yè)面跳轉(zhuǎn)還是組件間調(diào)用,都采用CC統(tǒng)一的組件調(diào)用方式完成。

  • DDComponentForAndroid

得到的方案采用路由 + 接口下沉的方式,所有接口下沉到base中,組件中實(shí)現(xiàn)接口并在IApplicationLike中添加代碼注冊(cè)到Router中。

  • ModularizationArchitecture

組件間調(diào)用需指定同步實(shí)現(xiàn)還是異步實(shí)現(xiàn),調(diào)用組件時(shí)統(tǒng)一拿到RouterResponse作為返回值,同步調(diào)用的時(shí)候用RouterResponse.getData()來獲取結(jié)果,異步調(diào)用獲取時(shí)需要自己維護(hù)線程。

  • ARouter

阿里推出的路由引擎,是一個(gè)路由框架,并不是完整的組件化方案,可作為組件化架構(gòu)的通信引擎。

  • 聚美Router

聚美的路由引擎,在此基礎(chǔ)上也有聚美的組件化實(shí)踐方案,基本思想是采用路由 + 接口下沉的方式實(shí)現(xiàn)組件化。

美團(tuán)其他團(tuán)隊(duì)組件化方案調(diào)研

美團(tuán)收銀ComponentCenter

美團(tuán)收銀的組件化方案支持接口調(diào)用和消息總線兩種方式,接口調(diào)用的方式需要構(gòu)建CCPData,然后調(diào)用ComponentCenter.call,最后在統(tǒng)一的Callback中進(jìn)行處理。消息總線方式也需要構(gòu)建CCPData,最后調(diào)用ComponentCenter.sendEvent發(fā)送。美團(tuán)收銀的業(yè)務(wù)組件都打包成AAR上傳至倉(cāng)庫(kù),組件間存在相互依賴,這樣導(dǎo)致mainapp引用這些組件時(shí)需要小心地exclude一些重復(fù)依賴。在我們的組件化方案中,我們采用了一種巧妙的方法來解決這個(gè)問題。

美團(tuán)App ServiceLoader

美團(tuán)App的組件化方案采用ServiceLoader的形式,這是一種典型的接口調(diào)用組件通信方式。用注解定義服務(wù),獲取服務(wù)時(shí)取得一個(gè)接口的List,判斷這個(gè)List是否為空,如果不為空,則獲取其中一個(gè)接口調(diào)用。

WMRouter

美團(tuán)外賣團(tuán)隊(duì)開發(fā)的一款A(yù)ndroid路由框架,基于組件化的設(shè)計(jì)思路。主要提供路由、ServiceLoader兩大功能。之前美團(tuán)技術(shù)博客也發(fā)表過一篇WMRouter的介紹:《WMRouter:美團(tuán)外賣Android開源路由框架》。WMRouter提供了實(shí)現(xiàn)組件化的兩大基礎(chǔ)設(shè)施框架:路由和組件間接口調(diào)用。支持和文檔也很充分,可以考慮作為我們團(tuán)隊(duì)實(shí)現(xiàn)組件化的基礎(chǔ)設(shè)施。

組件化方案

組件化基礎(chǔ)框架

在前期的調(diào)研工作中,我們發(fā)現(xiàn)外賣團(tuán)隊(duì)的WMRouter是一個(gè)不錯(cuò)的選擇。首先,WMRouter提供了路由+ServiceLoader兩大組件間通信功能,其次,WMRouter架構(gòu)清晰,擴(kuò)展性比較好,并且文檔和支持也比較完備。所以我們決定了使用WMRouter作為組件化基礎(chǔ)設(shè)施框架之一。然而,直接使用WMRouter有兩個(gè)問題:

  • 我們的項(xiàng)目已經(jīng)在使用一個(gè)路由框架,如果使用WMRouter,需要把之前使用的路由框架改成WMRouter路由框架。
  • WMRouter沒有消息總線框架,我們調(diào)研的其他項(xiàng)目也沒有適合我們項(xiàng)目的消息總線框架,因此我們需要開發(fā)一個(gè)能夠滿足我們需求的消息總線框架,這部分會(huì)在后面詳細(xì)描述。
  • 組件化分層結(jié)構(gòu)

    在參考了不同的組件化方案之后,我們采用了如下分層結(jié)構(gòu):

  • App殼工程:負(fù)責(zé)管理各個(gè)業(yè)務(wù)組件和打包APK,沒有具體的業(yè)務(wù)功能。
  • 業(yè)務(wù)組件層:根據(jù)不同的業(yè)務(wù)構(gòu)成獨(dú)立的業(yè)務(wù)組件,其中每個(gè)業(yè)務(wù)組件包含一個(gè)Export Module和Implement Module。
  • 功能組件層:對(duì)上層提供基礎(chǔ)功能服務(wù),如登錄服務(wù)、打印服務(wù)、日志服務(wù)等。
  • 組件基礎(chǔ)設(shè)施:包括WMRouter,提供頁(yè)面路由服務(wù)和ServiceLoader接口調(diào)用服務(wù),以及后面會(huì)介紹的組件消息總線框架:modular-event。
  • 整體架構(gòu)如下圖所示:

    業(yè)務(wù)組件拆分

    我們調(diào)研其他組件化方案的時(shí)候,發(fā)現(xiàn)很多組件方案都是把一個(gè)業(yè)務(wù)模塊拆分成一個(gè)獨(dú)立的業(yè)務(wù)組件,也就是拆分成一個(gè)獨(dú)立的Module。而在我們的方案中,每個(gè)業(yè)務(wù)組件都拆分成了一個(gè)Export Module和Implement Module,為什么要這樣做呢?

    1. 避免循環(huán)依賴

    如果采用一個(gè)業(yè)務(wù)組件一個(gè)Module的方式,如果Module A需要調(diào)用Module B提供的接口,那么Module A就需要依賴Module。同時(shí),如果Module B需要調(diào)用Module A的接口,那么Module B就需要依賴Module A。此時(shí)就會(huì)形成一個(gè)循環(huán)依賴,這是不允許的。

    也許有些讀者會(huì)說,這個(gè)好解決:可以把Module A和Module B要依賴的接口放到另一個(gè)Module中去,然后讓Module A和Module B都去依賴這個(gè)Module就可以了。這確實(shí)是一個(gè)解決辦法,并且有些項(xiàng)目組在使用這種把接口下沉的方法。

    但是我們希望一個(gè)組件的接口,是由這個(gè)組件自己提供,而不是放在一個(gè)更加下沉的接口里面,所以我們采用了把每個(gè)業(yè)務(wù)組件都拆分成了一個(gè)Export Module和Implement Module。這樣的話,如果Module A需要調(diào)用Module B提供的接口,同時(shí)Module B需要調(diào)用Module A的接口,只需要Module A依賴Module B Export,Module B依賴Module A Export就可以了。

    2. 業(yè)務(wù)組件完全平等

    在使用單Module方案的組件化方案中,這些業(yè)務(wù)組件其實(shí)不是完全平等,有些被依賴的組件在層級(jí)上要更下沉一些。但是采用Export Module+Implement Module的方案,所有業(yè)務(wù)組件在層級(jí)上完全平等。

    3. 功能劃分更加清晰

    每個(gè)業(yè)務(wù)組件都劃分成了Export Module+Implement Module的模式,這個(gè)時(shí)候每個(gè)Module的功能劃分也更加清晰。Export Module主要定義組件需要對(duì)外暴露的部分,主要包含:

    • 對(duì)外暴露的接口,這些接口用WMRouter的ServiceLoader進(jìn)行調(diào)用。
    • 對(duì)外暴露的事件,這些事件利用消息總線框架modular-event進(jìn)行訂閱和分發(fā)。
    • 組件的Router Path,組件化之前的工程雖然也使用了Router框架,但是所有Router Path都是定義在了一個(gè)下沉Module的公有Class中。這樣導(dǎo)致的問題是,無論哪個(gè)模塊添加/刪除頁(yè)面,或是修改路由,都需要去修改這個(gè)公有的Class。設(shè)想如果組件化拆分之后,某個(gè)組件新增了頁(yè)面,還要去一個(gè)外部的Java文件中新增路由,這顯然難以接受,也不符合組件化內(nèi)聚的目標(biāo)。因此,我們把每個(gè)組件的Router Path放在組件的Export Module中,既可以暴露給其他組件,也可以做到每個(gè)組件管理自己的Router Path,不會(huì)出現(xiàn)所有組件去修改一個(gè)Java文件的窘境。

    Implement Module是組件實(shí)現(xiàn)的部分,主要包含:

    • 頁(yè)面相關(guān)的Activity、Fragment,并且用WMRouter的注解定義路由。
    • Export Module中對(duì)外暴露的接口的實(shí)現(xiàn)。
    • 其他的業(yè)務(wù)邏輯。

    組件化消息總線框架modular-event

    前文提到的實(shí)現(xiàn)組件化基礎(chǔ)設(shè)施框架中,我們用外賣團(tuán)隊(duì)的WMRouter實(shí)現(xiàn)頁(yè)面路由和組件間接口調(diào)用,但是卻沒有消息總線的基礎(chǔ)框架,因此,我們自己開發(fā)了一個(gè)組件化消息總線框架modular-event。

    為什么需要消息總線框架

    之前,我們開發(fā)過一個(gè)基于LiveData的消息總線框架:LiveDataBus,也在美團(tuán)技術(shù)博客上發(fā)表過一篇文章來介紹這個(gè)框架:《Android消息總線的演進(jìn)之路:用LiveDataBus替代RxBus、EventBus》。關(guān)于消息總線的使用,總是伴隨著很多爭(zhēng)論。有些人覺得消息總線很好用,有些人覺得消息總線容易被濫用。

    既然已經(jīng)有了ServiceLoader這種組件間接口調(diào)用的框架,為什么還需要消息總線這種方式呢?主要有兩個(gè)理由。

    1. 更進(jìn)一步的解耦

    基于接口調(diào)用的ServiceLoader框架的確實(shí)現(xiàn)了解耦,但是消息總線能夠?qū)崿F(xiàn)更徹底的解耦。接口調(diào)用的方式調(diào)用方需要依賴這個(gè)接口并且知道哪個(gè)組件實(shí)現(xiàn)了這個(gè)接口。消息總線方式發(fā)送者只需要發(fā)送一個(gè)消息,根本不用關(guān)心是否有人訂閱這個(gè)消息,這樣發(fā)送者根本不需要了解其他組件的情況,和其他組件的耦合也就越少。

    2. 多對(duì)多的通信

    基于接口的方式只能進(jìn)行一對(duì)一的調(diào)用,基于消息總線的方式能夠提供多對(duì)多的通信。

    消息總線的優(yōu)點(diǎn)和缺點(diǎn)

    總的來說,消息總線最大的優(yōu)點(diǎn)就是解耦,因此很適合組件化這種需要對(duì)組件間進(jìn)行徹底解耦的場(chǎng)景。然而,消息總線被很多人詬病的重要原因,也確實(shí)是因?yàn)橄⒖偩€容易被濫用。消息總線容易被濫用一般體現(xiàn)在幾個(gè)場(chǎng)景:

    1. 消息難以溯源

    有時(shí)候我們?cè)陂喿x代碼的過程中,找到一個(gè)訂閱消息的地方,想要看看是誰(shuí)發(fā)送了這個(gè)消息,這個(gè)時(shí)候往往只能通過查找消息的方式去“溯源”。導(dǎo)致我們?cè)陂喿x代碼,梳理邏輯的過程不太連貫,有種被割裂的感覺。

    2. 消息發(fā)送比較隨意,沒有強(qiáng)制的約束

    消息總線在發(fā)送消息的時(shí)候一般沒有強(qiáng)制的約束。無論是EventBus、RxBus或是LiveDataBus,在發(fā)送消息的時(shí)候既沒有對(duì)消息進(jìn)行檢查,也沒有對(duì)發(fā)送調(diào)用進(jìn)行約束。這種不規(guī)范性在特定的時(shí)刻,甚至?xí)頌?zāi)難性的后果。比如訂閱方訂閱了一個(gè)名為login_success的消息,編寫發(fā)送消息的是一個(gè)比較隨意的程序員,沒有把這個(gè)消息定義成全局變量,而是定義了一個(gè)臨時(shí)變量String發(fā)送這個(gè)消息。不幸的是,他把消息名稱login_success拼寫成了login_seccess。這樣的話,訂閱方永遠(yuǎn)接收不到登錄成功的消息,而且這個(gè)錯(cuò)誤也很難被發(fā)現(xiàn)。

    組件化消息總線的設(shè)計(jì)目標(biāo)

    1. 消息由組件自己定義

    以前我們?cè)谑褂孟⒖偩€時(shí),喜歡把所有的消息都定義到一個(gè)公共的Java文件里面。但是組件化如果也采用這種方案的話,一旦某個(gè)組件的消息發(fā)生變動(dòng),都會(huì)去修改這個(gè)Java文件。所以我們希望由組件自己來定義和維護(hù)消息定義文件。

    2. 區(qū)分不同組件定義的同名消息

    如果消息由組件定義和維護(hù),那么有可能不同組件定義了重名的消息,消息總線框架需要能夠區(qū)分這種消息。

    3. 解決前文提到的消息總線的缺點(diǎn)

    解決消息總線消息難以溯源和消息發(fā)送沒有約束的問題。

    基于LiveData的消息總線

    之前的博文《Android消息總線的演進(jìn)之路:用LiveDataBus替代RxBus、EventBus》詳細(xì)闡述了如何基于LiveData構(gòu)建消息總線。組件化消息總線框架modular-event同樣會(huì)基于LiveData構(gòu)建。使用LiveData構(gòu)建消息總線有很多優(yōu)點(diǎn):

  • 使用LiveData構(gòu)建消息總線具有生命周期感知能力,使用者不需要調(diào)用反注冊(cè),相比EventBus和RxBus使用更為方便,并且沒有內(nèi)存泄漏風(fēng)險(xiǎn)。
  • 使用普通消息總線,如果回調(diào)的時(shí)候Activity處于Stop狀態(tài),這個(gè)時(shí)候進(jìn)行彈Dialog一類的操作就會(huì)引起崩潰。使用LiveData構(gòu)建消息總線完全沒有這個(gè)風(fēng)險(xiǎn)。
  • 組件消息總線modular-event的實(shí)現(xiàn)

    解決不同組件定義了重名消息的問題

    其實(shí)這個(gè)問題還是比較好解決的,實(shí)現(xiàn)的方式就是采用兩級(jí)HashMap的方式解決。第一級(jí)HashMap的構(gòu)建以ModuleName作為Key,第二級(jí)HashMap作為Value;第二級(jí)HashMap以消息名稱EventName作為Key,LiveData作為Value。查找的時(shí)候先用組件名稱ModuleName在第一級(jí)HashMap中查找,如果找到則用消息名EventName在第二級(jí)HashName中查找。整個(gè)結(jié)構(gòu)如下圖所示:

    對(duì)消息總線的約束

    我們希望消息總線框架有以下約束:

  • 只能訂閱和發(fā)送在組件中預(yù)定義的消息。換句話說,使用者不能發(fā)送和訂閱臨時(shí)消息。
  • 消息的類型需要在定義的時(shí)候指定。
  • 定義消息的時(shí)候需要指定屬于哪個(gè)組件。
  • 如何實(shí)現(xiàn)這些約束

  • 在消息定義文件上使用注解,定義消息的類型和消息所屬M(fèi)odule。
  • 定義注解處理器,在編譯期間收集消息的相關(guān)信息。
  • 在編譯器根據(jù)消息的信息生成調(diào)用時(shí)需要的interface,用接口約束消息發(fā)送和訂閱。
  • 運(yùn)行時(shí)構(gòu)建基于兩級(jí)HashMap的LiveData存儲(chǔ)結(jié)構(gòu)。
  • 運(yùn)行時(shí)采用interface+動(dòng)態(tài)代理的方式實(shí)現(xiàn)真正的消息訂閱和發(fā)送。
  • 整個(gè)流程如下圖所示:

    消息總線modular-event的結(jié)構(gòu)

    • modular-event-base:定義Anotation及其他基本類型
    • modular-event-core:modular-event核心實(shí)現(xiàn)
    • modular-event-compiler:注解處理器
    • modular-event-plugin:Gradle Plugin

    Anotation

    • @ModuleEvents:消息定義
    @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface ModuleEvents {String module() default ""; }
    • @EventType:消息類型
    @Retention(RetentionPolicy.SOURCE) @Target(ElementType.FIELD) public @interface EventType {Class value(); }

    消息定義

    通過@ModuleEvents注解一個(gè)定義消息的Java類,如果@ModuleEvents指定了屬性module,那么這個(gè)module的值就是這個(gè)消息所屬的Module,如果沒有指定屬性module,則會(huì)把定義消息的Java類所在的包的包名作為消息所屬的Module。

    在這個(gè)消息定義java類中定義的消息都是public static final String類型。可以通過@EventType指定消息的類型,@EventType支持java原生類型或自定義類型,如果沒有用@EventType指定消息類型,那么消息的類型默認(rèn)為Object,下面是一個(gè)消息定義的示例:

    //可以指定module,若不指定,則使用包名作為module名 @ModuleEvents() public class DemoEvents {//不指定消息類型,那么消息的類型默認(rèn)為Objectpublic static final String EVENT1 = "event1";//指定消息類型為自定義Bean@EventType(TestEventBean.class)public static final String EVENT2 = "event2";//指定消息類型為java原生類型@EventType(String.class)public static final String EVENT3 = "event3"; }

    interface自動(dòng)生成

    我們會(huì)在modular-event-compiler中處理這些注解,一個(gè)定義消息的Java類會(huì)生成一個(gè)接口,這個(gè)接口的命名是EventsDefineOf+消息定義類名,例如消息定義類的類名為DemoEvents,自動(dòng)生成的接口就是EventsDefineOfDemoEvents。消息定義類中定義的每一個(gè)消息,都會(huì)轉(zhuǎn)化成接口中的一個(gè)方法。使用者只能通過這些自動(dòng)生成的接口使用消息總線。我們用這種巧妙的方式實(shí)現(xiàn)了對(duì)消息總線的約束。前文提到的那個(gè)消息定義示例DemoEvents.java會(huì)生成一個(gè)如下的接口類:

    package com.sankuai.erp.modularevent.generated.com.meituan.jeremy.module_b_export;public interface EventsDefineOfDemoEvents extends com.sankuai.erp.modularevent.base.IEventsDefine {com.sankuai.erp.modularevent.Observable<java.lang.Object> EVENT1();com.sankuai.erp.modularevent.Observable<com.meituan.jeremy.module_b_export.TestEventBean> EVENT2();com.sankuai.erp.modularevent.Observable<java.lang.String> EVENT3(); }

    關(guān)于接口類的自動(dòng)生成,我們采用了square/javapoet來實(shí)現(xiàn),網(wǎng)上介紹JavaPoet的文章很多,這里就不再累述。

    使用動(dòng)態(tài)代理實(shí)現(xiàn)運(yùn)行時(shí)調(diào)用

    有了自動(dòng)生成的接口,就相當(dāng)于有了一個(gè)殼,然而殼下面的所有邏輯,我們通過動(dòng)態(tài)代理來實(shí)現(xiàn),簡(jiǎn)單介紹一下代理模式和動(dòng)態(tài)代理:

    • 代理模式: 給某個(gè)對(duì)象提供一個(gè)代理對(duì)象,并由代理對(duì)象控制對(duì)于原對(duì)象的訪問,即客戶不直接操控原對(duì)象,而是通過代理對(duì)象間接地操控原對(duì)象。
    • 動(dòng)態(tài)代理: 代理類是在運(yùn)行時(shí)生成的。也就是說Java編譯完之后并沒有實(shí)際的class文件,而是在運(yùn)行時(shí)動(dòng)態(tài)生成的類字節(jié)碼,并加載到JVM中。

    在動(dòng)態(tài)代理的InvocationHandler中實(shí)現(xiàn)查找邏輯:

  • 根據(jù)interface的typename得到ModuleName。
  • 調(diào)用的方法的methodname即為消息名。
  • 根據(jù)ModuleName和消息名找到相應(yīng)的LiveData。
  • 完成后續(xù)訂閱消息或者發(fā)送消息的流程。
  • 消息的訂閱和發(fā)送可以用鏈?zhǔn)秸{(diào)用的方式編碼:

    • 訂閱消息
    ModularEventBus.get().of(EventsDefineOfModuleBEvents.class).EVENT1().observe(this, new Observer<TestEventBean>() {@Overridepublic void onChanged(@Nullable TestEventBean testEventBean) {Toast.makeText(MainActivity.this, "MainActivity收到自定義消息: " + testEventBean.getMsg(),Toast.LENGTH_SHORT).show();}});
    • 發(fā)送消息
    ModularEventBus.get().of(EventsDefineOfModuleBEvents.class).EVENT1().setValue(new TestEventBean("aa"));

    訂閱和發(fā)送的模式

    • 訂閱消息的模式

    • observe:生命周期感知,onDestroy的時(shí)候自動(dòng)取消訂閱。
    • observeSticky:生命周期感知,onDestroy的時(shí)候自動(dòng)取消訂閱,Sticky模式。
    • observeForever:需要手動(dòng)取消訂閱。
    • observeStickyForever:需要手動(dòng)取消訂閱,Sticky模式。
    • 發(fā)送消息的模式

    • setValue:主線程調(diào)用。
    • postValue:后臺(tái)線程調(diào)用。

    總結(jié)

    本文介紹了美團(tuán)行業(yè)收銀研發(fā)組Android團(tuán)隊(duì)的組件化實(shí)踐,以及強(qiáng)約束組件消息總線modular-event的原理和使用。我們團(tuán)隊(duì)很早之前就在探索組件化改造,前期有些方案在落地的時(shí)候遇到很多困難。我們也研究了很多開源的組件化方案,以及公司內(nèi)部其他團(tuán)隊(duì)(美團(tuán)App、美團(tuán)外賣、美團(tuán)收銀等)的組件化方案,學(xué)習(xí)和借鑒了很多優(yōu)秀的設(shè)計(jì)思想,當(dāng)然也踩過不少的坑。我們逐漸意識(shí)到:任何一種組件化方案都有其適用場(chǎng)景,我們的組件化架構(gòu)選擇,應(yīng)該更加面向業(yè)務(wù),而不僅僅是面向技術(shù)本身。

    后期工作展望

    我們的組件化改造工作遠(yuǎn)遠(yuǎn)沒有結(jié)束,未來可能會(huì)在以下幾個(gè)方向繼續(xù)進(jìn)行深入的研究:

  • 組件管理:組件化改造之后,每個(gè)組件是個(gè)獨(dú)立的工程,組件也會(huì)迭代開發(fā),如何對(duì)這些組件進(jìn)行版本化管理。
  • 組件重用:現(xiàn)在看起來對(duì)這些組件的重用是很方便的,只需要引入組件的庫(kù)即可,但是如果一個(gè)新的項(xiàng)目到來,需求有些變化,我們應(yīng)該怎樣最大限度的重用這些組件。
  • CI集成:如何更好的與CI集成。
  • 集成到腳手架:集成到腳手架,讓新的項(xiàng)目從一開始就以組件化的模式進(jìn)行開發(fā)。
  • 參考資料

  • Android消息總線的演進(jìn)之路:用LiveDataBus替代RxBus、EventBus
  • WMRouter:美團(tuán)外賣Android開源路由框架
  • 美團(tuán)外賣Android平臺(tái)化架構(gòu)演進(jìn)實(shí)踐
  • 作者簡(jiǎn)介

    • 海亮,美團(tuán)高級(jí)工程師,2017年加入美團(tuán),目前主要負(fù)責(zé)美團(tuán)輕收銀、美團(tuán)收銀零售版等App的相關(guān)業(yè)務(wù)及模塊開發(fā)工作。

    招聘

    美團(tuán)餐飲生態(tài)誠(chéng)招Android高級(jí)/資深工程師和技術(shù)專家,Base北京、成都,歡迎有興趣的同學(xué)投遞簡(jiǎn)歷到chenyuxiang@meituan.com。

    總結(jié)

    以上是生活随笔為你收集整理的Android组件化方案及组件消息总线modular-event实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。