android組件化之路

問(wèn)題:實(shí)際業(yè)務(wù)變化快,而工程內(nèi)各個(gè)功能模塊耦合度太高,不能對(duì)功能模塊進(jìn)行快速方便地拆分或組裝。團(tuán)隊(duì)共同開(kāi)發(fā)中,可能一個(gè)文件同時(shí)被多人修改,導(dǎo)致每次更新提交代碼都需要消耗大量時(shí)間去merge代碼。每次修改,都需要進(jìn)行功能測(cè)試和系統(tǒng)測(cè)試。

目的:解決以上問(wèn)題,使項(xiàng)目可以靈活配置,功能模塊完全解耦,實(shí)踐組件化之路。

實(shí)現(xiàn):在之前的開(kāi)發(fā)中,一個(gè)應(yīng)用程序,我們將全部功能模塊都寫(xiě)在工程app包中。實(shí)踐組件化,我們將各個(gè)功能模塊獨(dú)立出來(lái),最終以依賴(lài)包的形式整合到app主Module中去。在這里我寫(xiě)了個(gè)項(xiàng)目demo,簡(jiǎn)單分了幾個(gè)功能模塊,應(yīng)用結(jié)構(gòu)如下圖所示:

項(xiàng)目組件化結(jié)構(gòu)圖

說(shuō)明:每一個(gè)組件module是一個(gè)子工程,子工程可以依賴(lài)基礎(chǔ)庫(kù)baselibrary可獨(dú)立運(yùn)行;也可以作為主工程的依賴(lài)庫(kù)。

具體實(shí)現(xiàn):1:配置項(xiàng)目的buildscript,如下圖所示:

buildscript配置

關(guān)于butterknife的配置及用法:http://jakewharton.github.io/butterknife,butterknife8支持在lib庫(kù)中注解。

2:在主app module gradle中如下配置:

applyplugin:'com.android.application'

applyplugin:'android-apt'

android {

? ? compileSdkVersion COMPILE_SDK_VERSION as int

? ? buildToolsVersion BUILD_TOOLS_VERSION

? ? defaultConfig {

? ? ? ? applicationId APPLICATION_ID

? ? ? ? minSdkVersion MIN_SDK_VERSIONas int

? ? ? ? targetSdkVersion TARGET_SDK_VERSIONas int

? ? ? ? versionCode 1

? ? ? ? versionName "1.0"

? ? }

? ? signingConfigs {

? ? ? ? debugConfig {

? ? ? ? ? ? storeFile file("***.jks")

? ? ? ? ? ? storePassword "******"

? ? ? ? ? ? keyAlias "*****"

? ? ? ? ? ? keyPassword "******"

? ? ? ? }

? ? releaseConfig {

? ? ? ? storeFile file("******.jks")

? ? ? ? storePassword "********"

? ? ? ? keyAlias "*****"

? ? ? ? keyPassword"*******"

? ? }

}

}

?buildTypes {

? ? ? ?release {

? ? ? ? ?minifyEnabled false

? ? ? ? ?proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

? ? ?}

? }

dependencies {

if(!isDebug.toBoolean()) {//各個(gè)模塊作為庫(kù)加載

compile project(':loginmodule')

compile project(':startmodule')

compile project(':homemodule')

compile project(':msgmodule')

}else{//各模塊獨(dú)立運(yùn)行

compile project(':baselibrary')

}

//router

apt'com.github.mzule.activityrouter:compiler:1.1.7'

}

說(shuō)明:關(guān)于activityrouter的配置及使用,在后面會(huì)說(shuō)到。

3:baselibrary作為各個(gè)模塊共同依賴(lài)的基礎(chǔ)庫(kù),其gradle配置如下:

applyplugin:'com.android.library'

applyplugin:'com.jakewharton.butterknife'

applyplugin:'android-apt'

android {

compileSdkVersion24

buildToolsVersion"25.0.2"

defaultConfig {

minSdkVersion15

targetSdkVersion24

versionCode1

versionName"1.0"

}

buildTypes {

release {

minifyEnabledfalse

proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

}

}

}

dependencies {

compile fileTree(include: ['*.jar'],dir:'libs')

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {

excludegroup:'com.android.support',module:'support-annotations'

})

compile'com.android.support:appcompat-v7:24.2.1'

compile'com.jakewharton:butterknife:8.5.1'

apt'com.jakewharton:butterknife-compiler:8.5.1'

compile'com.github.mzule.activityrouter:activityrouter:1.2.2'

}

4:在子工程模塊gradle配置如下(以homemodule為例):

if(isDebug.toBoolean()) {

applyplugin:'com.android.application'

}else{

applyplugin:'com.android.library'

}

applyplugin:'com.jakewharton.butterknife'

applyplugin:'android-apt'

android {

compileSdkVersion24

buildToolsVersion"25.0.2"

defaultConfig {

minSdkVersion15

targetSdkVersion24

versionCode1

versionName"1.0"

testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {

release {

minifyEnabledfalse

proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

}

}

sourceSets {

main{

if(isDebug.toBoolean()) {

manifest.srcFile'src/debug/AndroidManifest.xml'

}else{

manifest.srcFile'src/release/AndroidManifest.xml'

}

}

}

resourcePrefix"home_"

}

dependencies {

compile fileTree(dir:'libs',include: ['*.jar'])

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {

excludegroup:'com.android.support',module:'support-annotations'

})

compile project(':baselibrary')

apt'com.jakewharton:butterknife-compiler:8.5.1'

//router

apt'com.github.mzule.activityrouter:compiler:1.1.7'

}

說(shuō)明:當(dāng)module單獨(dú)運(yùn)行和作為module運(yùn)行時(shí),其activity在manifest中設(shè)置也會(huì)不同,這里可以根據(jù)isDebug設(shè)置不同的manifest。當(dāng)分別開(kāi)發(fā)模塊時(shí),容易出資源重復(fù)命名的問(wèn)題,可以在build.gradle中設(shè)置resourcePrefix "home_",通過(guò)給模塊設(shè)置不同的資源前綴,可以避免重復(fù)命名。

Activity跳轉(zhuǎn)問(wèn)題

從上面的配置中,可以看到,項(xiàng)目引入了apt'com.github.mzule.activityrouter:compiler:1.1.7',我們?yōu)槭裁词褂肁ctivityRouter呢,當(dāng)我們把各個(gè)功能模塊抽成獨(dú)立的lib的時(shí)候,各個(gè)模塊之間難免要進(jìn)行Activity的跳轉(zhuǎn)及傳參。我們不能再像以前那樣直接通過(guò)startActivity來(lái)實(shí)現(xiàn)跳轉(zhuǎn)了。關(guān)于ActivityRouter的配置及用法:https://github.com/mzule/ActivityRouter

使用在application中注解:@Modules({"app","homeModule","loginModule","startModule","msgModule"})

public class XxxxApplication extends Application {

}

每個(gè)module中創(chuàng)建空java類(lèi)注解:

@Module("homeModule")

public class HomeModule{

}

組件間通信問(wèn)題:

不同組件Activity之間傳遞大量數(shù)據(jù)時(shí)可以通過(guò)EventBus來(lái)進(jìn)行傳遞,EventBus原理及用法:https://github.com/greenrobot/EventBus

編譯運(yùn)行

當(dāng)在gradle.properties中設(shè)置isDebug=true時(shí),可以獨(dú)立運(yùn)行每個(gè)module,獨(dú)立運(yùn)行調(diào)試,當(dāng)設(shè)置isDebug=false,可以編譯運(yùn)行整個(gè)project,注意isDebug變量設(shè)置改變時(shí),要重新對(duì)gradle進(jìn)行sync。

可能遇到的一些問(wèn)題:

1:如果遇到/com/github/mzule/activityrouter/router/RouterInit.java javaError:(7, 5) 錯(cuò)誤: 找不到符號(hào) 符號(hào):? 變量 RouterMapping等錯(cuò)誤,請(qǐng)檢查app是否把各個(gè)Module都依賴(lài)進(jìn)來(lái)了。

2:使用butterknife注解時(shí),每個(gè)Module會(huì)對(duì)應(yīng)生成R2文件,即使在base庫(kù)里注解過(guò)了,Module也要重新注解,組件中不能直接使用。

3:如果項(xiàng)目中使用到menu注意:

@Override

protected void onMenuItemClick(MenuItem item) {

//? ? ? ? switch (item.getItemId()) {

//? ? ? ? ? ? case R2.id.xxx:

//? ? ? ? ? ? ? ? Routers.open(mContext,"");

//? ? ? ? ? ? ? ? break;

//? ? ? ? }

if (item.getItemId() == R.id.xxx){

Routers.open(mContext,"");

}

super.onMenuItemClick(item);

}

尋找對(duì)應(yīng)的menu id時(shí),用if else 代替 switch,注:itemid 和 R2值不一樣,和R是一樣的。

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容