Android徹底組件化—代碼和資源隔離

得到Android組件化方案已經(jīng)開源,參見Android組件化方案開源。方案的解讀文章是一個小的系列,這是系列的第三篇文章:
1、Android徹底組件化方案實踐
2、Android徹底組件化demo發(fā)布
3、Android徹底組件化-代碼和資源隔離
4、Android徹底組件化—UI跳轉升級改造
5、Android徹底組件化—如何使用Arouter

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

雖然沒有兼容問題,但在升級的過程中也收獲了意外之喜,那就是發(fā)現(xiàn)gradle3.0.0對代碼隔離的支持越來越好。為什么對“代碼隔離”這么關注呢?大家可以回顧前兩篇文章Android徹底組件化方案實踐Android徹底組件化demo發(fā)布,在這兩篇文章中提到的JIMU組件化方案,被我冠以“徹底”二字,雖然有些說大話,但主要是為了強調JIMU與之前其他組件化方案的不同之處就在于,JIMU實現(xiàn)了組件之間的絕對隔離,不同組件之間在代碼開發(fā)階段是完全不可見的,是一種徹底解耦的思想。為了實現(xiàn)這種隔離,我人為在編譯和運行期做了一次判斷和區(qū)分,既在編譯期間(開發(fā)期間)組件之間沒有任何依賴關系,但在打包和運行時,再偷偷添加依賴。具體可以參見前兩篇文章和github源碼。

不得不說,當時這種實現(xiàn)是迫不得已,我本來想直接使用gradle提供的功能來做這種隔離,其實gradle也的確提供一個類似的功能,那就是apk依賴語法,其作用就是保證依賴庫只在運行期間對外可見,但在編譯期間是不可見的。按說這已經(jīng)滿足我的要求了,但是遇到了一個坑:在gradle2.+版本,apk依賴只能是jar,不能是aar,但是我們的組件因為含有各種資源,輸出產物就是aar!所以最終選擇了放棄apk這種語法。

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

一、代碼隔離

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

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

組件A依賴lib1,既A implementation lib1
組件B依賴組件A,既B api A

在gradle3.0.0之前,B是完全可以引用到lib1里面的類的,但是現(xiàn)在B在編譯期間就做不到了,只能在運行期可以。這種思想有點類似于“下屬的下屬不是你的下屬”的思想。但是這種隔離在組件之間是不起作用的,在上面的例子中A的所有類對B還是完全可見的,也就是沒有做任何隔離的。不過implementation的確是一種有效減少編譯時間的方式,還是上面的例子,lib1發(fā)生了變化,現(xiàn)在只需要編譯A就可以了,而在之前B有可能也使用到了lib1,所以需要同時編譯B和A。按照官方建議,大部分情況下都應該使用implementation來進行添加依賴。

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

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

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

從上圖可以看出,在代碼隔離效果上,runtimeOnly的效果是最好的!但是就可以直接使用了嗎,答案是否定的。

二、資源隔離

在前面的文章中,一直在強調代碼隔離,其實組件之間的完全隔離還有一層就是資源隔離,否則還是容易造成組件之間的耦合。這個在文章的“單獨調試”章節(jié)中提到了一句,就是每個組件都需要指定一個資源前綴resourcePrefix,以避免集成后資源名沖突的問題。也就是說,一個徹底的組件化不僅要做到代碼不能直接引用,資源也是不能引用的!

但是runtimeOnly目前還做到資源隔離,我在JIMU的開源庫上做了試驗,app通過runtimeOnly引用sharecomponent組件,雖然sharecomponent的代碼是不可見了,但是資源還是可以被app直接使用的并能成功運行。

從這一點上看,直接替換成runtimeOnly是不行的,為了達到這種效果,目前還是需要像JIMU一樣,人為的加一層控制,所以從組件化方案的角度上看并沒有變的更薄,不過幸好JIMU已經(jīng)很簡單了,有一定的gradle基礎的人可以比較容易的理解。

三、調試切換

除了上面說的資源隔離導致不能直接用runtimeOnly之外,還有一個使用上的問題需要解決,這也是JIMU中compbuild插件提供的一個功能:自動切換單獨調試和集成調試。在單獨調試時,組件是一個application工程,其輸出產物是apk文件,而在集成調試時,被依賴的組件是一個library工程,其輸出產物是aar文件。對于runtimeOnly來說,對aar和jar是支持的,但是不能支持apk,所以如果想在單獨調試和集成調試之間切換的話,需要人工修改runalone配置并修改build.gradle配置文件,然后還需要sync之后才能生效,這種修改是相當繁瑣的。

在JIMU中,這個問題的解決是通過“智能”識別當前要調試的組件來解決的,對于要調試的組件將其設置為application工程,而將其依賴的其他組件默默修改為library工程,這種修改是即時生效的,對開發(fā)者是完全透明的。開發(fā)者直接點擊AS的run功能區(qū)就可以隨意的調試任意組件。AS的run功能區(qū)的圖如下:


隨意的調試切換

四、總結

綜上所述,我們對JIMU和gradle3.0.0做幾點總結:
(1)升級到gradle3.0.0之后,可以繼續(xù)使用JIMU,不需要專門做兼容
(2)gradle3.0.0提供了implementation和runtimeOnly兩種語法,它們都能實現(xiàn)一定程度的代碼隔離效果,建議大家在今后優(yōu)先使用
(3)implementation和runtimeOnly目前在資源隔離和調試切換上還不能滿足組件化的要求,所以還是需要使用JIMU提供的完全隔離和隨意切換功能。

在JIMU的源碼中我增加了gradle3.0.0分支,依賴語法做了相應的替換源碼地址:DDComponent

JIMU的討論群,群號693097923,歡迎大家加入:


進群請掃碼
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,733評論 25 709
  • 得到Android組件化方案已經(jīng)開源,參見Android組件化方案開源。方案的解讀文章是一個小的系列,這是系列的第...
    格竹子閱讀 84,845評論 194 405
  • 什么是組件化?組件化開發(fā)就是將一個app分成多個模塊,每個模塊都是一個組件(Module),開發(fā)的過程中我們可以讓...
    碼農一顆顆閱讀 5,004評論 2 16
  • 讀貓叔逝去的味道,有感而發(fā) 還依稀記得第一次看到不語老師的微博,組織一次貓說共讀,毫不猶豫的就報名參加了,最近太浮...
    liny52閱讀 276評論 0 0
  • 今天兒子上完輔導班回家,很不情愿的對我說爸爸再沒有我同意不要給我報什么輔導班,這樣玩的時間都沒有了。 ...
    三一馬勝文爸爸閱讀 164評論 0 0

友情鏈接更多精彩內容