组件化的优点
- 编译速度:可以按需测试单一模块,因为每一个模块都可以当做一个application。
- 超级解耦:极度的降低了模块之前的耦合,便于后期维护。
- 功能重用:某一块的功能在另外的组件化项目中使用只需要单独依赖这一模块即可,例如login模块。
- 便于团队开发:适用于大团队分模块各自开发,更好地团队协作,提升工作效率。
组件化需要注意的点
- 要注意包名和资源文件名的冲突
Gradle
中版本号的统一管理- 组件在
Application
和Library
之间如何做到随意切换 AndroidManifest
文件的区分Library
不能在Gradle
文件中有applicationId
项目搭建
- 项目中新建模块(
member
和cart
)
注意:要选择
Application
,不要选择Module

各个模块都可直接运行,因为都是
Application
。
- 编写
common.gradle
:统一整个项目各个模块的gradle、依赖库版本以及配置,放在项目根目录,与根build.gradle
平级
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
- 各个模块
apply from: "../common.gradle"
,删除通用配置,保留独有配置
apply from: "../common.gradle"
android {
defaultConfig {
applicationId "com.zt.member"
}
}
dependencies {
}
注意:
applicationId
添加到各自模块中,因为每个模块都是唯一的
- 使组件在
Application
和Library
之间随意切换,其实就是apply plugin: "com.android.application"
还是apply plugin: "com.android.library"
编写config.gradle
,定义一个开关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
整个项目,应该是可以编过,并且各个模块也是可以单独编译成 App 的。
但是,毕竟整个项目还是一个完整的 App ,那除了app
模块是Application
外,其他模块应该都是Library
,那就修改isApplication: false
- 修改各个模块的
gradle
文件,因为如果是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 {
// 只有当模块为Library时,才可以进行依赖
if (!rootProject.ext.android.isApplication) {
implementation project(path: ":member")
implementation project(path: ":cart")
}
}
-
Androidmanifest
文件的区分,需要使得当组件在Application
和Library
下加载不同的Androidmanifest
.
在模块中新建manifest
文件夹,路径:src/main/manifest
,复制一份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
的话,每个模块都需要一个xxxApplication
,但是当组件变成Library
的话,xxxApplication
就不需要了,也不需要打包到最终的app
中,那就需要进行配置了,思路与AndroidManifest
文件类似
在模块中新建debug
文件夹(名字自取),并添加包名,随后将临时代码文件添加到该目录下,如: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"
}
}
}
注意:请注意
debug
前面图标的颜色,如果是蓝色(isApplication: true
),则表示这里面的java
文件会被编译进app
中,如果是灰色(isApplication: false
),则表示不会。
-
java
代码中区分模块类型
首先现在common.gradle
中使用buildConfigField
添加参数
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0.0"
// 添加参数,便于在java文件中使用 buildConfigField type name value
buildConfigField "boolean", "isApplication", "$rootProject.ext.android.isApplication"
}
Make Project
之后,会在各个模块的BuildConfig
文件中生成出该字段,这样代码中就可以使用了。

- 最后,可以再建立个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")
}
网友评论