组件化、模块化本质上差不多,但是因为组件化可以转成应用的,方便团队化开发,同时个人开发的话也比较好提高效率,比如个人开发中,你开发了一款登录组件,然后其他项目要用了,或者其他同事要用了,你就可以直接把这个组件复制给它,然后那边的项目或者你的同事复制来后就可以直接用了,达到类似插拔一样的效果,极为方便,省去重复造轮子的麻烦,同时还可以降低项目复杂性,提升开发效率;
上面只是我的浅显理解
组件化理论上来说分成3层,应用层(app壳层)、业务组件层、基础库层,其中业务组件层是依赖各个业务组件层的,然后也要依赖基础库层,然后业务组件层各个层是不互相依赖的,这个就是重点了,在项目比较复杂的时候,这个业务组件层就是可以分给其他人去开发,然后等开发完成后,在由一个管理项目的人去把这个业务组件层依赖进到app壳层,具体框架如图所示:
。图虽然有点潦草,但是问题不大嗷,大概就这个意思
下面来说下具体怎么去实现,还有途中碰到的坑
1.组件化编译版本、第三方库统一管理
在app根目录下创建个配置的gradle脚本
然后手写配置,其中这块要注意的是要看你当前项目的gradle版本,具体坑,请参考组件化-gradle的ext在不同版本的gradle的用法_z936689039的博客-CSDN博客,这里会教我们咋用ext这种扩展方式去配置一个全局的编译版本,第三方库那些,这块我这里的做法是这样的,
def dep = [:]
def android = [:]
android.gradle_plugin = 'com.android.tools.build:gradle:3.5.1'
dep.android = android
def android_support=[:]
android_support.support='com.android.support:support-v4:22.2.1'
android_support.appcompat='com.android.support:appcompat-v7:22.2.1'
android_support.constraint='com.android.support.constraint:constraint-layout:1.1.3'
dep.android_support=android_support
def support_test=[:]
support_test.runner='com.android.support.test:runner:1.0.2'
support_test.espresso='com.android.support.test.espresso:espresso-core:3.0.2'
dep.support_test=support_test
dep.junit = 'junit:junit:4.12'
def build = [:]
build.javaVersion = JavaVersion.VERSION_1_8
build.compileSdkVersion = 22
build.buildToolsVersion='28.0.3'
build.minSdkVersion = 14
build.targetSdkVersion = 22
build.BuildVersionCode = 150
build.BuildVersionName = "1.5.0"
dep.build = build
ext.dep = dep
配置好后再项目的build.gradle下引入这个配置
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
apply from: "config.gradle"
repositories {
google()
mavenCentral()
}
dependencies {
classpath dep.android.gradle_plugin
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
然后就是日常在各个模块配置了
2.配置好就添加模块咯,这个估计都知道,我直接截图咯
然后就哦了
3.然后替换下你刚添加的模块中的build.gradle的那些什么编译版本呀,第三方库,support或者androidX 库那些,换成第一步中已经配置好的那些,便于后期管理,要是不这么配置的话,会因为编译的版本不一样,导致编译失败的
def build=dep.build;
android {
compileSdkVersion build.compileSdkVersion
buildToolsVersion build.buildToolsVersion
defaultConfig {
applicationId "com.glde.dlr.module_login"
minSdkVersion build.minSdkVersion
targetSdkVersion build.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility build.VERSION_1_8
targetCompatibility build.VERSION_1_8
}
}
dependencies {
implementation dep.android_support.support
implementation dep.android_support.appcompat
implementation dep.android_support.constraint
androidTestImplementation dep.support_test.runner
androidTestImplementation dep.support_test.espresso
}
4.然后配置全局变量,区分模块是应用application还是library,这块主要就是为了区分你这个应用是开发调试的时候,还是说准备上线的时候,开发调试的时候,当然就说你设置为application嘛,不用通过app模块运行,直接运行你自己开发的那个业务组件模块,但是当你要上线了,你就要把这个状态改成上线状态了,变成library,不能da
这块可以放在之前配置好的config.gradle里头,也可以说放在gradle.properties里头
加这么一句话
#false为应用模块,否则为library模块 isRelease=false
这个isRelease随便你取名字,我这里是为了方便我后面维护叫这个鬼名字的
然后再各个模块加上判断
就这个,下面的那个是
def build = dep.build
compileSdkVersion build.compileSdkVersion
这个东西就是之前3中配置好的
配置好后,我们可以看到,当
isRelease=false的时候,此时所有的模块都是应用级别的
你看所有模块都是可以运行的,因为各个业务组件模块它跟app主模块是同一个级别的
当设置为true的时候,此时各个模块就是library了
我们发现只有app主模块是可以正常运行的
5.然后添加基础组件层,这个就直接创建个library就行了,这块不在说了
1.当把业务模块的转变成library的时候,运行编译的时候Android Studio会提示
> Library projects cannot set applicationId. applicationId is set to 'com.glde.dlr.module_login' in default config.
这个提示很明显了,library不能有applicationId,解决方法就是添加判断就好了
在applicationId处,添加
if(!isRelease.toBoolean()){
applicationId "com.glde.dlr.module_login"
}
这样就好了
2.如果有多个base基础库,并且每个业务模块都要引用的话,怎么处理会比较方便呢,这里推荐这么做:
在config.gradle中添加base基础库的配置
//配置公共基础库层
dep.dependice=[
other:[
":library_base"(基础library的名字)
]
]
这块我等于是说声明了个other数组
然后在各个组件下的build.gradle下进行遍历获取它,然后进行依赖,直接上代码
dep.dependice.other.each{
implementation project(it)
}
其中each是遍历的意思,it就是other里头的东西
3.同样是当业务组件的application切换到library的时候,假如你业务组件的AndroidManifest.xml里头有配置个application,那么问题就来了,当你module变成library的时候,它是不允许有name,还有其他那些application的那些花里胡哨的属性的,就比如说,
拿本文中的应用配置举例子哈
isRelease=false,此时业务组件为还在开发中的,那么你在开发的时候,肯定会配置及其相关熟悉的,类似
这样的,然后当你变成library后,就不需要这么多属性了,那么这块怎么处理会比较方便呢,有个解决方法,下面看操作:
1.在业务组件项目下的src/main下创建一个文件夹,然后新增一个AndroidManifest.xml文件
2.在build.gradle中添加如下代码:
android{
...
sourceSets {
//解决资源冲突问题,比如调试的时候(应用模块)有application,
// 与library(发版后的集成到app模块后变成lib)的application冲突
main {
if (isRelease.toBoolean()) {
manifest.srcFile 'src/main/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
}
}
}
}
嗯,这样就好了,这样就不用每次在上线的时候还去手动修改AndroidManifest.xml,麻烦,而且还容易忘记这个事,那到时候就尴尬了
至此,组件化算是创建完成了,下一篇开始讲解,业务组件间如何跳转,从零开始手写路由跳转