开发时经常是多人协同开发,每个人负责不同的功能,首先由项目主负责人搭建项目框架,之后每个人通过 git 下载项目,然后就开始开发各自的功能。有些独立的功能模块自成一个 module,比如相机相册、二维码等等,这样可以提高工程的复用性,不同module需要使用你的模块直接跳转过来即可。虽然抽出来一个独立的module,但是如何把这个module变成一个独立的application更加方便我们的编译、调试和开发呢?而不是开发时需要编译整个项目,这样的编译速度大打折扣,例如我们的项目,编译一次就需要好几分钟,这是不能容忍的。这个时候我们就可以单独的创建一个 Application ,最后合并时只需把你的 Application 当成一个 Module,壳工程直接跳转到你的 Module 就可以了。这样在开发过程中只用编译自己的application即可,可以极大提高我们的开发效率。无需编译整个project,就是因为功能模块在开发过程中以Application的形式存在。当业务功能整合时,才以Library的形式存在。
那么自己创建的 Module 怎么才能变成 Application 呢?或者说 Module 和 Application 之间怎样切换方便调试?下面将详细介绍
看完整项目
config.gradle内容就是配置了一些基础参数,是否切换成application的参数isModule就在这个文件里,后续我们修改这个值就可以完成library与application的切换。
ext { //extend
// false: 组件模式
// true :集成模式
isModule = false
android = [
compileSdkVersion: 28,
minSdkVersion : 15,
targetSdkVersion : 28,
versionCode : 1,
versionName : "1.0"
]
appId = ["app" : "com.example.dn_component",
"module1": "com.example.module1",
"module2" : "com.example.module2" ]
supportLibrary = "28.0.0"
dependencies = [
"appcompat-v7" : "com.android.support:appcompat-v7:${supportLibrary}",
]
}
(1)根目录引入这个config.gradle文件:
//相当于引入头文件 将 config中的内容引入进来
apply from: "config.gradle"
(2)各个module以及主工程的build处的使用如下,也即各个module的gradle文件使用config中的统一变量进行配置:
//赋值与引用
def cfg = rootProject.ext.android
def appId = rootProject.ext.appId
android {
compileSdkVersion cfg.compileSdkVersion
defaultConfig {
minSdkVersion cfg.minSdkVersion
targetSdkVersion cfg.targetSdkVersion
versionCode cfg.versionCode
versionName cfg.versionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
javaCompileOptions {
annotationProcessorOptions {
arguments = [ moduleName : project.getName() ]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
从上图中我们可以看到有两个AndroidManifest.xml,一个在app目录下,一个在module下,主要是做什么用的呢?下面先看一下在module2的gradle配置文件中android {}中的一段配置:
//资源配置
sourceSets{
main{
//在组件模式下 使用不同的manifest文件
if(!isModule){
manifest.srcFile 'src/main/module/AndroidManifest.xml'
java.srcDirs 'src/main/module/java','src/main/java'}else{
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
isModule变量的作用主要用来配置这个用户中心模块是不是需要集成到主的APP中去,如果是true则是集成到主APP,这个模块就会变成library库,如果是false,那么它就可以当成APP安装到用户手机上。这是因为在module2中的build.gradle文件中加入了这样的代码来控制此库是library还是APP:
if (isModule) { apply plugin: 'com.android.library' } else { apply plugin: 'com.android.application' }
(1)module2的gradle配置文件如下(根据config中的isModule参数进行判断是library还是Application):
//apply plugin: 'com.android.library'
//根据isModule标签动态的切换 集成/组件模式
if (isModule){
apply plugin: 'com.android.library'
}else{
apply plugin: 'com.android.application'
}
def cfg = rootProject.ext.android
def appId = rootProject.ext.appId
android {
compileSdkVersion cfg.compileSdkVersion
defaultConfig {
minSdkVersion cfg.minSdkVersion
targetSdkVersion cfg.targetSdkVersion
versionCode cfg.versionCode
versionName cfg.versionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
javaCompileOptions {
annotationProcessorOptions {
arguments = [ moduleName : project.getName() ]
}
}
//添加一条 boolean类型的变量
buildConfigField("boolean","isModule",String.valueOf(isModule))
//组件模式下
if (!isModule){
applicationId appId['module2']
}
//资源配置
sourceSets{
main{
//在组件模式下 使用不同的manifest文件
if(!isModule){
manifest.srcFile 'src/main/module/AndroidManifest.xml'
java.srcDirs 'src/main/module/java','src/main/java'
}else{
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':base')
}
这里我们新建的是普通的Android module,后面自己手动添加了这么几个目录,系统创建的module是没有application和layout、默认的activity这些的,步骤如下:
(2)新建activity、以及布局文件、manifest文件、application
新建的这些都是空的,只是manifest里面需要添加入口的activity即可,这里需要维护两套manifest.xml文件:
public class Module2Activity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_module2);
}
}
如此我们只需要在config.gradle配置文件中的改动一下isModule变量的参数即可实现用户模块的可插拔形式集成和独立运行。
配置完上述步骤后,我们这里就有了两个可选择编译的application,
当然,当开发完毕,需要将module2编译到主工程时,把config.gradle文件中的isModule置为true即可。
完整的项目地址:https://github.com/buder-cp/DesignPattern/tree/master/buder_DN_component