一.简介
组件化开发中,我们可能会有很多的Module。那么就会有很多的Gradle文件。再加上项目本身的三个Gradle文件。每一个Gradle中使用的各种依赖需要统一管理。下面我们来讲解各个Module统一配置Gradle文件的内容。
二.配置
1.项目截图
2.说明
component_base 是基础Module 包含一些公共的引用,比如 约束布局constraintlayout。不可单独运行。
component_main 是主Module 可以单独运行。
component_ui 是UI相关Nodule 可以单独运行。
3.自定义的Gradle文件内容
ext {
/** true 每个业务Module可以单独开发 false 每个业务Module以lib的方式运行 */
isComponentMainModule = true//Main组件
isComponentUIModule = true//UI组件
/** 项目中各种版本号管理 */
versions = [
compileSdkVersion : 30,//compileSdkVersion
applicationId : "com.wjn.componentdemo",//应用ID
minSdkVersion : 16,//minSdkVersion
targetSdkVersion : 30,//targetSdkVersion
versionCode : 1,//版本号
versionName : "1.0.0",//版本名称
javaVersion : 1.8,//Java SDK版本号
appcompatVersion : "1.2.0",//appcompat版本号
materialVersion : "1.2.1",//material版本号
constraintlayoutVersion: "2.0.2",//ConstraintLayout版本号
junitVersion : "4.13.2",//junit版本号
]
/** 项目中dependencies依赖管理 */
dependencies = [
appcompat : "androidx.appcompat:appcompat:${versions["appcompatVersion"]}",
material : "com.google.android.material:material:${versions["materialVersion"]}",
constraintlayout: "androidx.constraintlayout:constraintlayout:${versions["constraintlayoutVersion"]}",
junit : "junit:junit:${versions["junitVersion"]}",
]
}
4.APP的Gradle文件内容
plugins {
id 'com.android.application'
}
android {
compileSdkVersion rootProject.ext.versions.compileSdkVersion
defaultConfig {
applicationId rootProject.ext.versions.applicationId
minSdkVersion rootProject.ext.versions.minSdkVersion
targetSdkVersion rootProject.ext.versions.targetSdkVersion
versionCode rootProject.ext.versions.versionCode
versionName rootProject.ext.versions.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility rootProject.ext.versions.javaVersion
targetCompatibility rootProject.ext.versions.javaVersion
}
}
dependencies {
/** 公共依赖包 */
implementation project(':component_base')
/** 是否加载 component_main */
if (!Boolean.valueOf(rootProject.ext.isComponentMainModule)) {
implementation project(':component_main')
}
/** 是否加载 component_ui */
if (!Boolean.valueOf(rootProject.ext.isComponentUIModule)) {
implementation project(':component_ui')
}
}
5.component_base组件的Gradle文件内容
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.versions.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.versions.minSdkVersion
targetSdkVersion rootProject.ext.versions.targetSdkVersion
versionCode rootProject.ext.versions.versionCode
versionName rootProject.ext.versions.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility rootProject.ext.versions.javaVersion
targetCompatibility rootProject.ext.versions.javaVersion
}
}
dependencies {
api rootProject.ext.dependencies["appcompat"]
api rootProject.ext.dependencies["material"]
api rootProject.ext.dependencies["constraintlayout"]
api rootProject.ext.dependencies["junit"]
}
注意:为了避免项目中多个Module重复依赖相同的依赖问题,比如可能多个Module都会依赖约束布局constraintlayout。这样我们抽出一个Base的Module,然后在这个Module中通过api的方式引入需要的依赖。这样其他的Module只需要引入该Base即可。然后每个Module单独使用的依赖,还是和普通项目一样使用implementation引入相关依赖即可。
6.component_main组件的Gradle文件内容
/** 修改处1:根据isComponentMainModule字段 决定该Module的产物*/
if (Boolean.valueOf(rootProject.ext.isComponentMainModule)) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
android {
compileSdkVersion rootProject.ext.versions.compileSdkVersion
defaultConfig {
/** 修改处2:根据isComponentMainModule字段 决定是否可以有applicationId 只有单独运行时才可以有applicationId*/
if (Boolean.valueOf(rootProject.ext.isComponentMainModule)) {
applicationId "com.wjn.component.main"
}
minSdkVersion rootProject.ext.versions.minSdkVersion
targetSdkVersion rootProject.ext.versions.targetSdkVersion
versionCode rootProject.ext.versions.versionCode
versionName rootProject.ext.versions.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
/** 修改处3:sourceSets闭包 配置不同文件夹的清单文件 根据isComponentMainModule字段 */
sourceSets {
main {
if (Boolean.valueOf(rootProject.ext.isComponentMainModule)) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
compileOptions {
sourceCompatibility rootProject.ext.versions.javaVersion
targetCompatibility rootProject.ext.versions.javaVersion
}
}
dependencies {
/** 公共依赖包 */
implementation project(':component_base')
/** 本Module独立使用的依赖 */
}
7.component_ui组件的Gradle文件内容
/** 修改处1:根据isComponentUIModule字段 决定该Module的产物*/
if (Boolean.valueOf(rootProject.ext.isComponentUIModule)) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
android {
compileSdkVersion rootProject.ext.versions.compileSdkVersion
defaultConfig {
/** 修改处2:根据isComponentUIModule字段 决定是否可以有applicationId 只有单独运行时才可以有applicationId*/
if (Boolean.valueOf(rootProject.ext.isComponentUIModule)) {
applicationId "com.wjn.component.ui"
}
minSdkVersion rootProject.ext.versions.minSdkVersion
targetSdkVersion rootProject.ext.versions.targetSdkVersion
versionCode rootProject.ext.versions.versionCode
versionName rootProject.ext.versions.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
/** 修改处3:sourceSets闭包 配置不同文件夹的清单文件 根据isComponentUIModule字段 */
sourceSets {
main {
if (Boolean.valueOf(rootProject.ext.isComponentUIModule)) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
compileOptions {
sourceCompatibility rootProject.ext.versions.javaVersion
targetCompatibility rootProject.ext.versions.javaVersion
}
}
dependencies {
/** 公共依赖包 */
implementation project(':component_base')
/** 本Module独立使用的依赖 */
}
三.验证
为了验证上述配置是否正确,咱们打两个包。一个包是两个Module单独运行,一个包是两个Module作为组件为壳工程使用。
1.两个Module单独运行
<1> 配置开关
isComponentMainModule = true//Main组件
isComponentUIModule = true//UI组件
<2> 打出的包清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0.0"
android:compileSdkVersion="30"
android:compileSdkVersionCodename="11"
package="com.wjn.componentdemo"
platformBuildVersionCode="30"
platformBuildVersionName="11">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="30" />
<uses-permission
android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.INTERNET" />
<application
android:theme="@ref/0x7f0f0196"
android:label="@ref/0x7f0e001b"
android:icon="@ref/0x7f0c0000"
android:allowBackup="true"
android:supportsRtl="true"
android:roundIcon="@ref/0x7f0c0001"
android:appComponentFactory="androidx.core.app.CoreComponentFactory">
<activity
android:name="com.wjn.componentdemo.MainActivity">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.wjn.component.base.BaseMainActivity" />
<activity
android:name="com.wjn.component.base.BaseTestActivity" />
</application>
</manifest>
<3> 运行及验证结果
运行正常,且清单文件中不包含两个Module的Activity。验证成功。
2.两个Module作为组件为壳工程使用
<1> 配置开关
isComponentMainModule = false//Main组件
isComponentUIModule = false//UI组件
<2> 打出的包清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0.0"
android:compileSdkVersion="30"
android:compileSdkVersionCodename="11"
package="com.wjn.componentdemo"
platformBuildVersionCode="30"
platformBuildVersionName="11">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="30" />
<uses-permission
android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.INTERNET" />
<application
android:theme="@ref/0x7f0f0196"
android:label="@ref/0x7f0e001b"
android:icon="@ref/0x7f0c0000"
android:allowBackup="true"
android:supportsRtl="true"
android:roundIcon="@ref/0x7f0c0001"
android:appComponentFactory="androidx.core.app.CoreComponentFactory">
<activity
android:name="com.wjn.componentdemo.MainActivity">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.wjn.component.main.MainMainActivity" />
<activity
android:name="com.wjn.component.ui.UIMainActivity" />
<activity
android:name="com.wjn.component.ui.UITestActivity" />
<activity
android:name="com.wjn.component.base.BaseMainActivity" />
<activity
android:name="com.wjn.component.base.BaseTestActivity" />
</application>
</manifest>
<3> 运行及验证结果
运行正常,且清单文件中包含两个Module的所有Activity。验证成功。
四.总结
通过三篇文章的讲解,我们就完成了组件化的初步配置,下面我们来总结一下。
1.前言
普通项目的缺点(尤其是项目稍微复杂一些时)
<1> 编译运行一次很慢。
<2> 修改其中一个点,可能也需要对其他模块进行简单的测试。
<3> 提交代码很容易造成代码冲突。
<4> 排查问题,比较麻烦。
<5> ...
2.模块化
Android Studio中,新建一个工程默认有一个App module。然后我们还可以通过File->New->New Module 新建module。那么这里的“module” 实际就是“模块”的意思。那么模块化相比普通的项目的优点是什么呢?它相比组件化的缺点是什么呢?
<1> 相比普通项目优点
解决了刚刚说的普通项目的缺点。
<2> 相比组件化缺点
[2.1] 每个模块不能独立运行。
[2.2] 项目比较复杂时,每个模块间存在相互依赖。
[2.3] ...
3.组件化的优点
<1.1> 各个组件可以单独运行,方便调试。
<1.2> 我们可以把一些基础的内容放到一个基础的组件中,比如 定位功能 网络请求功能 Json解析功能 原生UI功能等等。这样其他组件只需要依赖这个基础的组件即可。其他组件不需要相互依赖。
<1.3> 组件化中依赖原则是上层可以依赖下层,下层不可依赖上层,同层之间也尽量不要相互依赖。
<1.4> ...
4.组件化注意事项
组件化开发中除了刚刚说的依赖问题,还需要注意一下内容。
为了使每一个Module既可以单独运行又可以依附壳工程运行,需要修改几个点
<1> 修改清单文件
<2> 修改Gradle文件
详情:https://blog.youkuaiyun.com/weixin_37730482/article/details/70243289