android完全組件化番外篇-gradle3.0.0

最近Google正式推出AS3.0版本,同時gradle插件也升級爲3.0.0,目前各大開源庫都在作gradle3.0.0的兼容,我也把獲得開源的組件化方案AndroidComponent進行了升級,結論是:DDComponent在gradle3.0上是沒有兼容問題的,能夠直接使用。關於如何遷移到gradle3.0.0,請參見官方遷移指南html

雖然沒有兼容問題,但在升級的過程當中也收穫了意外之喜,那就是發現gradle3.0.0對代碼隔離的支持愈來愈好。爲何對「代碼隔離」這麼關注呢?你們能夠回顧前兩篇文章Android完全組件化方案實踐Android完全組件化demo發佈,在這兩篇文章中提到的DDComponent組件化方案,被我冠以「完全」二字,雖然有些說大話,但主要是爲了強調DDComponent與以前其餘組件化方案的不一樣之處就在於,DDComponent實現了組件之間的絕對隔離,不一樣組件之間在代碼開發階段是徹底不可見的,是一種完全解耦的思想。爲了實現這種隔離,我人爲在編譯和運行期作了一次判斷和區分,既在編譯期間(開發期間)組件之間沒有任何依賴關係,但在打包和運行時,再偷偷添加依賴。具體能夠參見前兩篇文章和github源碼android

不得不說,當時這種實現是無可奈何,我原本想直接使用gradle提供的功能來作這種隔離,其實gradle也的確提供一個相似的功能,那就是apk依賴語法,其做用就是保證依賴庫只在運行期間對外可見,但在編譯期間是不可見的。按說這已經知足個人要求了,可是遇到了一個坑:在gradle2.+版本,apk依賴只能是jar,不能是aar,可是咱們的組件由於含有各類資源,輸出產物就是aar!因此最終選擇了放棄apk這種語法。git

而在最新的gradle3.0.0上,apk被替換爲runtimeOnly語法,其做用仍是同樣的,可是我發現runtimeOnly能夠添加aar依賴!這的確讓我很興奮,這不就是我求之不得的功能嗎?有了這個尚方寶劍,組件化的方案就能夠作的更薄了啊。因而我對在獲得app上進行了實驗,結論是:runtimeOnly的確能夠解決一些問題,可是還不夠。下面我從代碼隔離、資源隔離和調試切換(單獨和集成)三個方便仔細闡述,也順便再講一下DDComponent所能實現的功能。github

1、代碼隔離

在講代碼隔離以前,先大體看一下gradle3.0.0對添加依賴的語法變化。api

首先compile被廢棄了,而是分紅了兩個:implementation和api,其中api與以前的compile功能基本一致,再也不贅述;implementation就比較高級了,其做用就是,使用implementation添加的依賴不會再編譯期間被其餘組件引用到,但在運行期間是徹底可見的。這也是一種代碼隔離。舉個例子,bash

組件A依賴lib1,既A implementation lib1
組件B依賴組件A,既B api A
複製代碼

在gradle3.0.0以前,B是徹底能夠引用到lib1裏面的類的,可是如今B在編譯期間就作不到了,只能在運行期能夠。這種思想有點相似於「下屬的下屬不是你的下屬」的思想。可是這種隔離在組件之間是不起做用的,在上面的例子中A的全部類對B仍是徹底可見的,也就是沒有作任何隔離的。不過implementation的確是一種有效減小編譯時間的方式,仍是上面的例子,lib1發生了變化,如今只須要編譯A就能夠了,而在以前B有可能也使用到了lib1,因此須要同時編譯B和A。按照官方建議,大部分狀況下都應該使用implementation來進行添加依賴。app

此外還有兩種變化,原來的apk語法被runtimeOnly取代,provided被compileOnly取代,其做用仍是沒變。上文也講了,runtimeOnly有個極大的改動就是能夠支持aar了,可是compileOnly仍是隻能支持jar!ide

先作一個小結,目前gradle3.0.0的四種語法的功能和代碼隔離效果見下圖:組件化

四種語法的功能和代碼隔離效果

從上圖能夠看出,在代碼隔離效果上,runtimeOnly的效果是最好的!可是就能夠直接使用了嗎,答案是否認的gradle

2、資源隔離

在前面的文章中,一直在強調代碼隔離,其實組件之間的徹底隔離還有一層就是資源隔離,不然仍是容易形成組件之間的耦合。這個在文章的「單獨調試」章節中提到了一句,就是每一個組件都須要指定一個資源前綴resourcePrefix,以免集成後資源名衝突的問題。也就是說,一個完全的組件化不只要作到代碼不能直接引用,資源也是不能引用的!

可是runtimeOnly目前還作到資源隔離,我在DDComponent的開源庫上作了試驗,app經過runtimeOnly引用sharecomponent組件,雖然sharecomponent的代碼是不可見了,可是資源仍是能夠被app直接使用的並能成功運行。

從這一點上看,直接替換成runtimeOnly是不行的,爲了達到這種效果,目前仍是須要像DDComponent同樣,人爲的加一層控制,因此從組件化方案的角度上看並無變的更薄,不過幸虧DDComponent已經很簡單了,有必定的gradle基礎的人能夠比較容易的理解。

3、調試切換

除了上面說的資源隔離致使不能直接用runtimeOnly以外,還有一個使用上的問題須要解決,這也是DDComponent中compbuild插件提供的一個功能:自動切換單獨調試和集成調試。在單獨調試時,組件是一個application工程,其輸出產物是apk文件,而在集成調試時,被依賴的組件是一個library工程,其輸出產物是aar文件。對於runtimeOnly來講,對aar和jar是支持的,可是不能支持apk,因此若是想在單獨調試和集成調試之間切換的話,須要人工修改runalone配置並修改build.gradle配置文件,而後還須要sync以後才能生效,這種修改是至關繁瑣的。

在DDComponent中,這個問題的解決是經過「智能」識別當前要調試的組件來解決的,對於要調試的組件將其設置爲application工程,而將其依賴的其餘組件默默修改成library工程,這種修改是即時生效的,對開發者是徹底透明的。開發者直接點擊AS的run功能區就能夠隨意的調試任意組件。AS的run功能區的圖以下:

隨意的調試切換

4、總結

綜上所述,咱們對DDComponent和gradle3.0.0作幾點總結: (1)升級到gradle3.0.0以後,能夠繼續使用DDComponent,不須要專門作兼容 (2)gradle3.0.0提供了implementation和runtimeOnly兩種語法,它們都能實現必定程度的代碼隔離效果,建議你們在從此優先使用 (3)implementation和runtimeOnly目前還在資源隔離和調試切換上還能知足組件化的要求,因此仍是須要使用DDComponent提供的徹底隔離和隨意切換功能。

在DDComponent的源碼中我增長了gradle3.0.0分支,依賴語法作了相應的替換,歡迎你們繼續支持「獲得」app出品的組件化方案,源碼地址:https://github.com/mqzhangw/AndroidComponent

相關文章
相關標籤/搜索