上一篇文章介紹了android組件化開發(fā)的意思邏輯和基本思路砸王,具體可以看這里攻旦。但是除了基本的思路外抖格,這種開發(fā)方式雖然對多人協(xié)同開發(fā)厢汹、項目管理和后期維護有很多好處螟深,但是同樣在開發(fā)過程中也有很多的坑。這一部分就主要介紹組件化開發(fā)需要注意的問題和解決方法烫葬。
1.module之間的引用
在AS 3.0之后界弧,gradle的compile已經(jīng)被廢棄,取而代之的是implementation和api搭综。這兩個的區(qū)別一般只需要記住一點:implementation引入的各種子模塊是無法被更高層的module使用的垢箕,而api可以。
舉個栗子:A module 引入了B module兑巾,B module引入了C module条获,如果使用的是implementation方式,那么C對于A來說是不可見的蒋歌;而使用api方式A是可以使用C中的方法的帅掘。同理,把C換成開源庫堂油、so文件修档、aar文件、jar包文件結(jié)論也適用府框。
2.不同module之間jar包的引用
這里再單獨說一下jar包文件吱窝,同樣舉個栗子:A module引入了B module,B module出于某種需求在lib中添加了c.jar包。這是如果A要使用相關(guān)的api院峡,必須在A module也聲明c.jar包兴使,不然一般情況下api會拋出異常。B module中對c.jar的聲明就是一般的gradle配置的常用方式照激,在對應(yīng)module的build.gradle
文件中添加如下代碼:
...
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
...
}
而在A module中发魄,c.jar的路徑需要變?yōu)橄鄬β窂?/p>
repositories {
flatDir {
dirs 'libs', '../moduleB/libs'//第一個表示A模塊本身的lib文件夾,第二個表示相對于A模塊俩垃,c.jar所在的路徑
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
...
}
同時需要注意為了能讓A模塊使用c.jar欠母,Bmoudle的配置文件使用的是api方式引入。
3.不同module的build.gradle配置維護
對于不同的module吆寨,很多的gradle配置其實是比較重復(fù)的,比如SDK支持的版本號踩寇,一些常用的suppor包引入等啄清。以com.android.support:appcompat
為例,不同的module如果引入的版本不同俺孙,輕則構(gòu)建時發(fā)出警告辣卒,嚴(yán)重時可能直接導(dǎo)致構(gòu)建失敗。所以睛榄,我們需要維護一個統(tǒng)一的全局版本荣茫。這里我門需要用到根目錄的config.gradle
文件。沒有的話可以自行新建一個场靴。
ext {
android = [
compileSdkVersion: 27,
buildToolsVersion: "27.0.2",
minSdkVersion : 19,
targetSdkVersion : 26
]
dependencies = [
project : [
moduleBase : ':moduleSystem:moduleBase',
moduleCommon : ':modulePublic:moduleCommon',
moduleUser : ':moduleCore:moduleUser'
],
"support:appcompat-v7" : 'com.android.support:appcompat-v7:27.0.2',
"support:design" : 'com.android.support:design:27.0.2',
"junit:4.12" : 'junit:junit:4.12'
]
}
內(nèi)部的名稱和嵌套層級都是可以自定義的啡莉,使用的時候以rootProject.ext
開頭,例如rootProject.ext.dependencies["support:appcompat-v7"]
旨剥。這樣如果需要對配置做修改咧欣,只需要修改一處就可以了。
4.不同module之間的數(shù)據(jù)通訊
因為AS項目的機制問題轨帜,不同的module之間需要靠implementation和api的方式保持引入關(guān)系魄咕,而對于被引用或者平級之間的module,都是不可見的蚌父。這就導(dǎo)致這些module之間的數(shù)據(jù)交互出現(xiàn)了問題哮兰。
-
不同module之間的頁面跳轉(zhuǎn)
這里主要的解決方式是通過開源路由庫來解決,相關(guān)的庫可以在gayHub上去搜rout苟弛、router關(guān)鍵字喝滞。我在自己項目中使用的是阿里的ARouter。 -
不同module之間的事件響應(yīng)和消息傳遞
這個沒啥好說的了嗡午,eventbus解決之囤躁。5. build.gradle buildType統(tǒng)一
這個其實應(yīng)該算作是AS 3.0的新版本的坑,不過在這兒用到了大量的module,用AS 3.0的同學(xué)也就必須要做這個工作了狸演。我們知道在主app模塊的buidl.gradle文件中可以修改buildTypes來配置不同的apk構(gòu)建方式:
buildTypes {
debug {
}
//打包測試用(內(nèi)部非混淆打包測試服務(wù)器)
debugTest.initWith(buildTypes.debug)
debugTest {
}
releaseLocal {
}
//正式服務(wù)器(對外發(fā)布公開包)
releaseFormal.initWith(buildTypes.releaseLocal)
releaseFormal {
}
新特性總結(jié)為一句話就是主app的buildTypes有多少言蛇,在每個子module的配置中也得保持一致。子module中不一定需要具體的配置宵距,但是得保證每個都得有腊尚。例如這里有debug、debugTest满哪、releaseLocal婿斥、releaseFormal 4種,那么所有的子模塊也得有對應(yīng)的4中配置哨鸭。
6. 系統(tǒng)層繼承和改寫
在項目中通常會有下面這種需求民宿。我們一般會在系統(tǒng)層的moduleBase中寫一個自定義的BaseApplication.class
類。而在app中像鸡,我們通常會在Application中初始化一些額外的啟動配置活鹰,例如推送的初始化等,而很可能對于系統(tǒng)層而言只估,推送相關(guān)的module是不可見的志群,換言之,我們無法在moduleBase的BaseApplication.class
類中完成對應(yīng)的初始化操作蛔钙。
對于這種情況锌云,我采用的是在app層再自定義一個SystemApplication.class
類繼承BaseApplication.class
,并實現(xiàn)BaseApplication.class
的抽象方法的方式來對應(yīng)的操作吁脱。
另外桑涎,對于自定義的BaseActivity、BaseFragment也可以采用這種方式對自定義要求更高的動態(tài)權(quán)限進行類似的處理豫喧。