基於ARouter的Android組件化實現

網上組件化的文章不少,但大多數文章都從底層的細枝末節開始講述,由下而上給人一種這門技術「博大精深」望而生畏的感受。而我寫這篇文章的初衷就是由上而下,但願別人在閱讀的過程當中可以以爲「組件化原來也就是這幾個東西」的感受。git

首先咱們來看一下組件化項目和傳統項目的區別

在傳統的項目裏

咱們一般狀況下會有一個core的libary模塊和一個app的application模塊,業務中的邏輯都寫在app中各個功能模塊放到不一樣的包下。這樣作有如下幾個主要的缺點:
一、實際業務變化很是快,可是單一工程的業務模塊耦合度過高,牽一髮而動全身。
二、在開發過程當中,任何一位成員沒辦法專一於本身的功能點,影響開發效率。
三、多人聯合開發在版本管理中很容易出現衝突和代碼覆蓋的問題。
四、功能測試和系統測試每次都要進行。
五、不管分包作的再好,隨着項目的增大,項目會逐漸失去層次感,別人來接手的時候會很吃力。
六、咱們在debug一個小功能的時候每次修改代碼都須要從新build整個項目,這樣顯的很不合理。github

在組件化項目中

除了有commonLib和app組件外,咱們按照功能劃分各個業務組件(能夠劃分出app1,app2,app3,app4四個大組件),以前的包變成如今的模塊,增長了層次感;每一個功能模塊能夠單獨編譯,加快了編譯速度,也爲提供單元模塊測試提供了支持;多人開發只負責本身的模塊,直接避免了版本管理的衝突。編程

圖1-0組件化基本項目結構圖

在明白了組件化爲咱們解決的主要問題後咱們來看看須要怎麼作

初步實現組建化其實咱們最終要解決的問題就只有2個:架構

1.業務組件可集成編譯也可單獨編譯--經過配置gradle便可解決

2.業務組件之間的頁面跳轉以及通訊--使用阿里開源的ARouter便可解決

接下來咱們具體來看一下如何操做app

首先來看一下模塊間依賴的問題

咱們能夠參照×××的兩個組件(app1,app2)來配置,首先咱們項目基本結構以下:框架

0.png

咱們一共須要建4個組件,除了2個功能組件外還有一個基本的core組件和一個做爲啓動的app組件。ide

在建好項目後咱們須要給2個功能組件配置一個是否單獨編譯的開關:組件化

1.png

關於開關的配置位置這是一個問題,咱們把它添加在gradle.properties文件中,這樣咱們每次修改值的時候就能夠觸發gradle的從新構建,便於咱們單獨編譯組件。性能

咱們單獨編譯的開關配置好了,如今咱們來看看組件之間的依賴關係:測試

2.png

對於2個功能組件,咱們要爲它裝上咱們以前配置的是否單獨編譯的開關,咱們須要修改以下2個地方:

3.png

能夠看到咱們要修改的就是我紅框框住的地方,當咱們的開關打開的時候,咱們就把他當成一個單獨的application來編譯,而且賦予它一個獨一無二的applicationId,這樣咱們就能夠經過剛剛在gradle.properties中配置的開關來控制它是否單獨做爲一個application來編譯。

而對於主入口的app組件咱們則須要作以下的配置:

4.png

咱們除了須要配置基本的core組件依賴之外還須要在app組件的gradle文件中根據開關選擇是否須要依賴咱們的功能組件,這個和各個功能組件中的配置是相呼應的。

而對於其餘組件模塊,重複上述步驟便可完成組件化框架的搭建。

在完成了組件化框架的搭建後,須要解決業務組件之間的頁面跳轉以及通訊

首先,爲了方便各個組件之間的交互咱們借用了阿里的ARouter庫,因此在每一個非core的組件(包括主Application)中都強烈建議加入對ARouter和core的依賴。

首先來看各個組件頁面間是怎樣跳轉的

咱們以前已經依賴了ARouter(詳細用法參照https://github.com/alibaba/ARouter),咱們要用它來幫咱們實現跳轉須要如下幾步:

5.png

跳轉的方法就如上圖顯示,咱們須要標明目標頁面,附帶上要傳送的參數,而後調用navigation()就能夠跳轉了,不過有人問目標頁面怎麼看着就是一個路徑,它是怎樣定義的?

6.png

  • 首先要用@Route註解標註頁面,並在path變量中給頁面定義一個路徑
  • 對於傳送過來的變量咱們直接定義一個同名的字段用@Autowired變量標註,Arouter會對該字段自動賦值
  • 最後咱們還須要將該頁面注入到ARouter中(原理相似ButterKnife),讓他幫咱們完成咱們須要的工做

這樣,咱們就完成了頁面間的跳轉了,是否是比起咱們傳統的方法更加簡單合理?

而後來看組件間如何通訊

這裏我想在app2組件中調用app1組件的sayHello方法來Toast一我的的名字,那app1組件的方法怎樣才能被其餘組件(包括主組件和其餘組件)調用

  • 首先在core組件裏建立一個暴露方法的接口,並定義接口簽名,同時繼承 Iprovider 接口

7.png

  • 而後在app1組件中繼承core裏定義的接口,並實現簽名方法。這裏咱們一樣使用Arouter的 @Router註解來提供此次服務的路由

8.png

  • 最後,咱們在其餘模塊使用 @Autowired 註解就能夠調用該方法了

9.png

能夠看到咱們一樣使用了@Autowired註解來初始定baseService服務,並將頁面注入Arouter中便可調用服務中的方法,且對於服務的依賴是基於接口的依賴,大大提升了其靈活性!

基本組件化框架的搭建就完成了,但願認真看完的朋友能有所收穫!若有不正之處還望指正!

關於組件化的思考

  • 組件的動態裝載與卸載。業務組件大多都須要有本身的Application,而後在這裏作相關的初始化操做,在集成模式下,只能是主組件能夠有Application,那麼問題一,業務組件怎麼獲取這個全局惟一的Application.問題二,業務組件的大量初始化操做,怎麼統一到主組件纔有的Application,假如全部初始化都放到主Application,那麼啓動速度和性能開銷若是保證。
  • 代碼隔離。有一個隱患沒有解決,那就是咱們可使用compile project(':xxx')來引入組件,雖然咱們使用了接口+實現的架構,組件之間必須針對接口編程,可是一旦咱們引入了(特別是主app引入)xxx組件,那就徹底能夠直接使用到其中的實現類,這樣咱們針對接口編程的規範就成了一紙空文。千里之堤毀於蟻穴,只要有代碼(不管是有意仍是無心的)這麼作了,咱們前面的工做就白費了。

以上兩個思考如何解決,歡迎各位在git issues

以上項目git(歡迎參與改進)

github.com/YoungBill/A…

相關文章
相關標籤/搜索