新建一个项目,该项目中包含:app(壳工程)、common(功能组件)、login(业务组件)。其中common组件是网络封装、图片封装、常用工具类封装,login组件是供登录功能业务的封装。下面是实现组件化项目的详细操作步骤。
步骤一:新建一个Project,取名为ModuleDemo
步骤二:新建“Module”,选择的“Android Library”,取名module_common
步骤三:新建“Module”,选择的“Phone & Tablet”,取名module_fun_login
注:Android Library与Phone & Tablet的区别:Android Library编译之后是arr文件,Phone & Tablet编译之后是可运行的apk。
现在整个工程中有4个build.gradle文件,分别位于属于app、module_fun_login、common_module、ModuleDemo。
步骤四:修改ModuleDemo的build.gradle文件
(整个Project的gradle文件,在这个gradle文件中使用ext定义的一些属性,其他module可以直接使用),在其中定义一些常用全局通用的配置属性,如complileSdk、minSdk等
ext { // Sdk and tools compileSdkVersion = 32 minSdkVersion = 21 targetSdkVersion = 28 versionCode = 1 versionName = "1.0"}
步骤五:分别修改app、module_fun_login、common_module工程下的build.gradle文件
使用rootProject.ext.xxx引入在步骤四定义的常量,如下图
步骤六:在步骤四中ept中新增一个Boolean类型的变量,取名为isRelease 。
注:isRelease 变量是为了实现自动化配置切换组件模式与集成化模式。
步骤七:修改组件module_fun_login下的build.gradle文件,添加isRelease条件判断。
注:选择“Phone & Tablet”新建的组件,将该组件集成到项目中时不能含有“com.android.application”与applicationId ,不然会出现“Library projects cannot set applicationId.”错误。而在单独测试时,该组件又是可以作为单独的apk来运行的。为了实现这种自动化配置,在步骤六新建一个Boolean变量,根据这个Boolean我们来决定组件的具体作用。而且下方步骤八与步骤九也是为了实现这个功能来配置的
注释或者删除
plugins { id 'com.android.application'}
添加
if (rootProject.ext.isRelease) {apply plugin: 'com.android.library'} else {apply plugin: 'com.android.application'}
为defaultConfig下的applicationId也添加上isRelease判断
if (!rootProject.ext.isRelease){applicationId "com.module.fun.login"}
步骤八:module_fun_login组件中的manifest.xml文件修改与合并
在module_fun_login组件先 main/java目录下新建debug文件夹,然后将module_fun_login 的manifest.xml文件copy到debug文件夹。修改module_fun_login 中main/manifest.xml 文件,将application里面的属性全部删除,同时只保留activity的声明,而debug文件夹下面的manifest.xml保持不变。后续新建的activity在这两个manifest.xml文件中都要注册。
步骤九:在module_fun_login的build.gradle文件添加sourceSets ,为“manifest.xml”添加判断isRelease,
在“android{}”中添加sourceSets
sourceSets {
main {
if (rootProject.ext.isRelease)
{
manifest.srcFile 'src/main/AndroidManifest.xml'
} else
{
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
}
}
}
步骤十:在组件common_module的build.gradle文件添加各类需要的依赖库
注:不要使用implementation,使用api。
//XXPermissions
api 'com.github.getActivity:XXPermissions:16.6'
//retrofit
api 'com.squareup.retrofit2:retrofit:2.5.0'
api 'com.squareup.retrofit2:converter-gson:2.5.0'
api 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
//Rxjava
api 'io.reactivex.rxjava2:rxjava:2.2.5'
api 'io.reactivex.rxjava2:rxandroid:2.1.0'
//eventbus
api 'org.greenrobot:eventbus:3.1.1'
//butterknife
api 'com.jakewharton:butterknife:10.2.3'
//glide
api 'com.github.bumptech.glide:glide:4.14.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
//okhttp
api "com.squareup.okhttp3:okhttp:4.10.0"
如下图
步骤十一:引入module_fun_login、common_module组件。
在app(壳工程)下的build.gradle文件添加
implementation project(path: ':common_module')
implementation project(path: ':module_fun_login')
在module_fun_login组件下的build.gradle文件添加
implementation project(path: ':common_module')
为何要使用组件化
了解组件化之前,我们先了解一下单一工程模式。在单一功能模式下,所有的业务逻辑都在一个工程里,业务之间存在相互调用,耦合度较高,代码可能出现重复。随着功能的不断添加,项目结构也越来越复杂。其他项目有相似的功能,剥离出来也比较费时费力。
api与implementation的区别
假设app依赖ModuleA,ModuleA依赖moduleB:implementation是隐藏依赖,当ModuleA使用implementation来依赖ModuleB的时候,app可以使用ModuleA的所有接口,但是不能使用ModuleB的接口。api是显示依赖,当ModuleA使用api来依赖ModuleB的时候。app不仅可以使用ModuleA的接口,也可以使用ModuleB的接口。
关于组件化的一些问题
1. 在Project下的build.gradle定义配置常量是为了方便版本管理,修改一个地方,其他地方的引用也会跟着修改了。但这也不是必须的。
2.资源文件命名问题,在各个组件新增资源文件时为了避免重名,最好是按照组件模块命名,在资源名称添加模块名,这样就可以避免资源命名引起的冲突问题。
3.组件之间的跳转实现:业务功能组件之间跳转可以使用阿里的ARouter (https://github.com/alibaba/ARouter/blob/master/README_CN.md)
网友评论