組件化的優(yōu)點(diǎn)
- 編譯速度:可以按需測(cè)試單一模塊,因?yàn)槊恳粋€(gè)模塊都可以當(dāng)做一個(gè)application。
- 超級(jí)解耦:極度的降低了模塊之前的耦合,便于后期維護(hù)。
- 功能重用:某一塊的功能在另外的組件化項(xiàng)目中使用只需要單獨(dú)依賴這一模塊即可,例如login模塊。
- 便于團(tuán)隊(duì)開發(fā):適用于大團(tuán)隊(duì)分模塊各自開發(fā),更好地團(tuán)隊(duì)協(xié)作,提升工作效率。
組件化需要注意的點(diǎn)
- 要注意包名和資源文件名的沖突
Gradle中版本號(hào)的統(tǒng)一管理- 組件在
Application和Library之間如何做到隨意切換 AndroidManifest文件的區(qū)分Library不能在Gradle文件中有applicationId
項(xiàng)目搭建
- 項(xiàng)目中新建模塊(
member和cart)
注意:要選擇
Application,不要選擇Module

項(xiàng)目結(jié)構(gòu)
各個(gè)模塊都可直接運(yùn)行,因?yàn)槎际?code>Application。
- 編寫
common.gradle:統(tǒng)一整個(gè)項(xiàng)目各個(gè)模塊的gradle、依賴庫(kù)版本以及配置,放在項(xiàng)目根目錄,與根build.gradle平級(jí)
apply plugin: "com.android.application"
apply plugin: "kotlin-android"
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
}
注意:
common.gradle中不要添加applicationId
- 各個(gè)模塊
apply from: "../common.gradle",刪除通用配置,保留獨(dú)有配置
apply from: "../common.gradle"
android {
defaultConfig {
applicationId "com.zt.member"
}
}
dependencies {
}
注意:
applicationId添加到各自模塊中,因?yàn)槊總€(gè)模塊都是唯一的
- 使組件在
Application和Library之間隨意切換,其實(shí)就是apply plugin: "com.android.application"還是apply plugin: "com.android.library"
編寫config.gradle,定義一個(gè)開關(guān)isApplication,也放在跟目錄
ext {
android = [
// true:所有組件均為application;false:所有組件均為library
isApplication: true
]
}
切換只需要修改isApplication的值即可。
- 在根
build.gradle中引用config.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "config.gradle"
buildscript {
...
}
allprojects {
...
}
- 修改
common.gradle
// app模塊一定為application,其他模塊參照配置
if (project.getName() == "app" || rootProject.ext.android.isApplication) {
apply plugin: "com.android.application"
} else {
apply plugin: "com.android.library"
}
apply plugin: "kotlin-android"
android {
...
}
dependencies {
...
}
到此為止,你sync整個(gè)項(xiàng)目,應(yīng)該是可以編過,并且各個(gè)模塊也是可以單獨(dú)編譯成 App 的。
但是,畢竟整個(gè)項(xiàng)目還是一個(gè)完整的 App ,那除了app模塊是Application外,其他模塊應(yīng)該都是Library,那就修改isApplication: false
- 修改各個(gè)模塊的
gradle文件,因?yàn)槿绻?code>Library的話,是不可以存在applicationId的。
apply from: "../common.gradle"
android {
defaultConfig {
if (rootProject.ext.android.isApplication) {
applicationId "com.zt.member"
}
}
}
dependencies {
}
既然是Library,那需要集成到app模塊中
-
app依賴其他組件,記得也要加上判斷
apply from: "../common.gradle"
android {
defaultConfig {
applicationId "com.zt.componentdemo"
}
}
dependencies {
// 只有當(dāng)模塊為L(zhǎng)ibrary時(shí),才可以進(jìn)行依賴
if (!rootProject.ext.android.isApplication) {
implementation project(path: ":member")
implementation project(path: ":cart")
}
}
-
Androidmanifest文件的區(qū)分,需要使得當(dāng)組件在Application和Library下加載不同的Androidmanifest.
在模塊中新建manifest文件夾,路徑:src/main/manifest,復(fù)制一份Androidmanifest.xml到該文件夾,并修改成Library適用的。
member 模塊
src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zt.member">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ComponentDemo">
<activity android:name=".MemberActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
src/main/manifest/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zt.member">
<application>
<activity android:name=".MemberActivity" />
</application>
</manifest>
- 修改
common.gradle,添加sourceSets,配置加載不同AndroidManifest文件。
android {
...
sourceSets {
main {
// 指定AndroidManifest文件路徑
if (project.getName() == "app" || rootProject.ext.android.isApplication) {
manifest.srcFile "src/main/AndroidManifest.xml"
} else {
manifest.srcFile "src/main/manifest/AndroidManifest.xml"
}
}
}
}
- 如果組件是
Application的話,每個(gè)模塊都需要一個(gè)xxxApplication,但是當(dāng)組件變成Library的話,xxxApplication就不需要了,也不需要打包到最終的app中,那就需要進(jìn)行配置了,思路與AndroidManifest文件類似
在模塊中新建debug文件夾(名字自?。⑻砑?strong>包名,隨后將臨時(shí)代碼文件添加到該目錄下,如:xxxApplication.java,xxxUtils.java等等
member 模塊
并在common.gradle中的sourceSets里添加配置
sourceSets {
main {
// 指定AndroidManifest文件路徑
if (project.getName() == "app" || rootProject.ext.android.isApplication) {
manifest.srcFile "src/main/AndroidManifest.xml"
java.srcDirs "src/main/debug"
} else {
manifest.srcFile "src/main/manifest/AndroidManifest.xml"
}
}
}
注意:請(qǐng)注意
debug前面圖標(biāo)的顏色,如果是藍(lán)色(isApplication: true),則表示這里面的java文件會(huì)被編譯進(jìn)app中,如果是灰色(isApplication: false),則表示不會(huì)。
-
java代碼中區(qū)分模塊類型
首先現(xiàn)在common.gradle中使用buildConfigField添加參數(shù)
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0.0"
// 添加參數(shù),便于在java文件中使用 buildConfigField type name value
buildConfigField "boolean", "isApplication", "$rootProject.ext.android.isApplication"
}
Make Project之后,會(huì)在各個(gè)模塊的BuildConfig文件中生成出該字段,這樣代碼中就可以使用了。

BuildConfig 路徑
- 最后,可以再建立個(gè)common模塊,這里新建選擇
Library即可
common 模塊
別忘了在common.gradle中添加依賴
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "com.google.android.material:material:1.2.1"
implementation "androidx.constraintlayout:constraintlayout:2.0.2"
implementation project (path: ":common")
}


