完全元件化框架Atoms-mvp

Vea發表於2018-09-03

完全元件化框架Atoms-mvp

前言

前一段時間看到JessYan的一篇文章,分享他的MVP開源框架,我相信大多數人應該都還有印象,不得不說這個框架確實很棒,感謝JessYan的開源和分享。框架雖然不是專案的核心,但卻是專案的基礎。一個好的專案框架,能幫助你快速地開始企業級專案開發。本人經過對MVPArms的研究考量並結合自己的想法與實際開發過程得到Atoms-MVP。

專案已開源Github,完全元件化的專案框架Atoms-mvp

什麼是元件化

元件化就是將一個完整的App按照關注點分離成多個元件,使得每個元件成為單獨的個體,做到元件內部的高聚合和元件之間低耦合。

為什麼我們要元件化?

巨集觀上講,元件化使開發人員更加專注於各模組的開發,使團隊成員更加方便迭代升級和維護,管理者也更容易統籌帷幄,規範專案層次和結構統一。微觀上講,元件化必將對基礎庫下沉從而提高複用,這也是專案框架演變進化過程中的的核心思想,對於子模組一個蘿蔔一個坑,互相不直接依賴,所以不用擔心變更帶來的風險。從根本上避免一個小小的改動牽連多處需要修改,導致迴歸整個App測試。對於測試同學而言,能有效的減少測試的時間,原有的業務不需要再次進行功能測試,只需專注於發生變化的業務,以及最終的整合測試即可

Atoms-mvp元件化過程

1.面向開發過程,維護成本,學習成本。化繁為簡,less is more,高擴充套件性為宗旨,使新手也能快速搭建自己的元件化專案

2.基礎庫下沉,只下沉最核心最必須,絕不拖泥帶水,納汙藏穢。

2.弱化了Dagger2的使用頻率,因為這對於一些新手來說Dagger2可能不是很好理解,排錯不是很好,但是對於一些頻繁使用到的Dagger程式碼我做了優化,省去了大量重複程式碼,幫助團隊加快開發速度。

3.網路請求方面使用Rxjava,okhttp,retrofit組合式框架但是並沒有使用RxCache處理快取,因為我覺得這樣會加重開發成本,增加編碼量和維護成本,其次Okhttp本身是自帶快取策略的,我們可以到後期真正需要的時候再使用快取框架

4.在設計架構時,將最原始,最需要,最重要的庫打入baseLib封裝成基礎庫,比如網路,support,依賴注入型框架dagger,以及和view相關的butterknife,或者其他的一些基礎庫,開發者可以自行擴充套件。目的是將這些充斥於整個介面相關的業務邏輯整合到最底層。往上一層封裝整個APP需要的公共服務。其中包括CommonSDK用來承上啟下,並提供ARouter路由框架,或者使用360Replugin外掛化框架,為元件之間解耦做鋪墊,開發者可視情況而定二選其一。以及業務服務庫和公共UI庫,統一整個APP的UI風格方便後期統一調整。再往上就是App的核心元件,各元件依賴公共層,元件之間絕對分離。最後整合在一起完美融合,形成一個APP應用系統

完全元件化框架Atoms-mvp

本專案特點

1.支援路由框架和外掛劃框架比如Arouter,RePlugin等

2.動態代理Application生命週期,各元件可做具體實現,使得子Module間接地擁有Application,能夠在子module中初始化相對當前nodule的的第三方庫。

3.各模組可配置單獨的ServiceApi,擁有屬於自己獨立的Api介面,同時還支援不同host場景

4.各元件資料傳輸面向介面不直接依賴於物件,使元件化解耦更徹底,做到完全元件化。在下面我會一一講到。

元件化的關鍵點

  • 程式碼隔離

程式碼隔離同樣也是程式碼解耦,每個元件之間程式碼互不侵入,互不依賴,團隊之間應具備規範的意識。除了人為上的約束,IDE工具gradle也為我們提供了很好的程式碼隔離語法,從AS3.0開始類庫依賴出現了四種新語法如下:

完全元件化框架Atoms-mvp

implementation對應以前的compile。與compile的區別在於使用implementation在編譯期間只對當前宿主可見,對其他宿主隔離。同時它還有一個好處是能夠加快編譯速度。打個比方如果宿主使用implementation引用庫的話,當宿主發生變化重新編譯時,庫不需要再編譯,只需要編譯這個宿主。而如果你使用的是compile引用庫的話,那麼兩者都需要重新編譯。所以在大部分情況下推薦使用implementation。從上圖可以看出,在程式碼隔離效果上,runtimeOnly的效果是最好的!所以如果引用子模組最好選擇runtimeOnly來保證程式碼完全隔離。而compileOnly這個語法就很有意思了,它的作用是依賴的類庫只參與編譯,而不會打包進Apk。基於這一點,一般情況下是用來引用編譯時註解的類庫,比如下面這個例子

  compileOnly "com.alibaba:arouter-compiler:1.1.4"
  compileOnly "com.jakewharton:butterknife-compiler:8.8.1"
  compileOnly  'com.google.dagger:dagger-compiler:2.15'
複製程式碼

這個例子是在元件的gradle檔案中,在這裡沒有引用與之相關的庫是因為在元件化專案中各元件都會依賴公共庫,而公共庫會依賴這些註解類庫的相關類庫。所以此時元件應該使用compileOnly依賴註解庫,不需要再引用於編譯註解相關的庫。 如果您在其他模組以compile的方式依賴了相同lib,最終在打包過程中可會出現重複程式碼,所以建議您採用compileOnly解決重複依賴的問題

其次我再補充說明一下資原始檔隔離。雖然上面解決了程式碼隔離但是對於資原始檔並沒有控制,其他宿主還是能夠訪問下級的資原始檔,為了避免編譯時衝突,可為資源名增加一個字首,約束資原始檔的命名規範。

android {
    resourcePrefix "gank_" //給 Module 內的資源名增加字首, 避免資源名衝突
}
複製程式碼
  • 各模組可裝配自己的Service域名

有些專案可能有多baseUrl的需求,這種情況Retrofit官方給了兩種解決方案,如下。

第一種:在 @Get , @Post註解中不僅可以傳相對路徑,還可以傳全路徑

完全元件化框架Atoms-mvp

第二種:將全路徑以引數@Url的形式傳遞給介面

完全元件化框架Atoms-mvp

  • 各元件可裝配自己的"Application"

對於有些子模組來說,它有屬於自己依賴的第三方庫,有些第三方庫需要在Application中初始化,而一個應用程式的Application物件只有一個,每個元件又全部分離出去了,那麼如何才能各元件共享?在Atoms-MVP中提供瞭解決方案。通過代理方式,委派一個AppDelegate物件去代理Application的生命週期。各各子模組只需在Manifest檔案中定義 meta標籤,指定真實被呼叫的Application生命週期類名,由Appdelegate建立時通過反射的手段初始化。貼一張圖方便理解

完全元件化框架Atoms-mvp

  • 資料傳遞

在元件化專案中,每個元件都是相對獨立,那麼他們之間如何進行資料傳遞呢?首先想到的是Intent、sp、file、廣播、內容提供者等這些常見的資料傳遞方式,但是剛剛說了元件之間是相對獨立的,不能直接把實體類傳遞過去,因為在完全解耦的元件化專案中,實體類不會下沉放到公共庫,也不會在多個元件之間存在依賴關係,只出現在於屬於它們自己的元件當中。那麼如何將實體類也完全解耦呢?Atoms-mvp提供了一套解決方案,每個元件如果需要對外提供資料傳遞,那麼統一在CommonService元件中宣告向外提供服務介面,具體的實現由需要傳遞資料的元件負責,完成跨模組資料傳遞。這樣做使得元件之間的互動不直接接觸,避免元件之間的直接依賴關係,只有做到這一點元件之間的才能徹底的元件化

總結

Android應用的架構,根據不同的應用場景和複雜程度使得技術架構也有不同,架構沒有好壞之分,只要適用於自己的業務就是好架構,每一次的重構每一次的更新都是為了節省人力和成本,提高開發效率。如果您正打算使用元件化框架完全可以把我的專案搬過去,改一改包名即可。同時Atoms-mvp也可以作為大家在進行元件化時的參考資料,如果您覺得我的文章寫的不錯,對您有幫助請為我點贊。

Atoms-mvp專案地址:github.com/xwc520/Atom…


參考文件:

www.jianshu.com/p/1c5afe686…

www.jianshu.com/p/f671dd768…

關於我Vea

簡書:www.jianshu.com/u/9184fed0c…

相關文章