本文我们先来说一下一下组件化。组件化很早就有了,网上也有很多例子。讲的都非常好,我这里也只是把自己在实际使用的情况做一下记录。
新项目中用到了组件化开发的思想。为什么要用到组件化呢?
因为本来公司项目是多个角色多种任务都在一个App中的。结果等我快完成的差不多的时候,老大说了,要拆开,每个角色单独拆成一个App。
我都快写完了你告诉要拆开?
需求分析(模块划分)
首先我们来分析一下,这个项目实际上是有4个角色,每个角色的任务是不同的,但是像登录,注册,图片上传,消息推送,导航等一些逻辑是基本上一模一样的。也就是说其实只有任务模块是不同的,其他模块的逻辑基本类似。
如果我按照以前的写法,所有的逻辑都是在app模块中的。如果拆成4个App的话,也就是意味着我要复制4分代码,然后没分代码都改一下。这么做实在是有些不合适。
那既然是只有任务模块区分较大,其他模块逻辑基本一样,那么,更好的办法就是把一些业务单独的作为module,然后项目直接依赖就可以了。
于是,我们可以根据业务来划分一下module。(模块的划分根据自身的业务去制定,我这里只是举个例子)
首先我们肯定要有一个common的模块,该模块是一些共用的代码,比如对BaseActivity、BaseFragment、网络框架等业务的封装。 (common)
然后任务肯定单独是个模块 (taskModule)
登录,注册,注销等业务可以放到用户模块中 (userModule)
消息,通知这些可以放到消息模块中 (messageModule)
导航我这里是集成的高德地图的SDK,对地图相关的业务可以单独封一个地图模块,方便以后其他项目使用 (gaodemaplib)
还有一些项目中使用的自定义view的东西,我们也是可以服用的,我这里也单独作为一个模块了 (custom_view)
好了基本上根据业务需求划分了这几个模块。
如图所示,大概结构就是这样。
这样一划分之后,实际上我们的绝大多数业务都是在各个module中完成的,而app则相当于一个组装的module,只需要配置一下启动页面和处理少量的逻辑就可以了,然后剩下的module我们可以直接通过import module的方式复用。这样也大大降低了耦合性。
对于我这个项目,我只需要完成一个app的逻辑,然后其他app依赖通用的module即可。基本上不需要做改动。
统一的gradle配置
模块划分完毕后我们需要解决的就是一些第三方库的依赖,以及默认的一些gradle配置了。
gradle是基于Groovy语言的,用于编写脚本。作为一名Android开发人员,我们很有必要去学习了解一下Groovy。
在我们平时项目中,我们经常会跟gradle文件打交道,因为Android Studio默认就是用gradle来进行构建的,我们在开发中也会对一些gradle文件进行编辑。
比如,依赖一些第三方的库,指定Android的版本,多渠道打包,指定签名文件等等。
首先我们先来解决统一配置的问题,我们多个模块之间对第三方的依赖应该保持一致,特别是官方的support包,必须保持一致,不然编译时会提示版本不一致的错误,关于版本不一致的解决办法可以看我之前的一篇博客
com.android.support冲突的解决办法
首先我们可以新建一个文件,用于声明android默认的配置项,签名文件的信息,以及依赖的第三方库的版本号。
例如
新建一个config.gradle文件,该文件主要是用来声明一些共用的变量。
类似于这样
ext {
/*defaultConfig*/
compile_sdk_version = 27
min_sdk_version = 16
target_sdk_version = 27
constraint_version = "1.0.2"
version_code = 101
version_name = "1.0.1"
multiDexEnabled = true
/*dependencies*/
android_support = "27.1.1"
butterknife = "8.5.1"
eventbus = "3.1.1"
glide = "4.7.1"
permission = "2.0.0-rc10"
retrofit = "2.4.0"
ok_http = "3.10.0"
rx_android = "2.0.2"
rx_java = "2.1.4"
rxlifecycle = "2.2.1"
dagger2 = "2.16"
/*等等*/
}
然后我们在project的build.grdle中引用该文件。
apply from: file('config.gradle')
image.png
注意路径不要错了,这样引入后我们就可以引用声明的变量了。
然后在module中的build.gradle中就可以使用我们声明好的变量了,这样一来,我们所有模块的版本就保持一致了,而且修改版本号的话只需要修改config.gradle中的变量值即可。
使用方法
模块的单独调试与相互依赖
在多人开发的模式下,可能每个人负责一个module,那么在调试的时候,我们需要把module单独作为一个application来调试。
这个时候,我们就需要准备两套清单配置文件。一套用于作为module时使用,另外一套作为application时使用,作为application时我们需要在清单配置文件中设置启动页面,主题等,而作为module的话,只需要声明一下需要的页面即可。
以userModule为例:
准备两套清单配置文件:
debug模式下的清单配置文件需要指定启动页,主题等
声明一个变量用来确定当前模块是不是一个module,例如
可以在跟目录的gradle.properties文件中声明,用起来也比较方便
isUserModule = true //true表示当前是个library,false则表示是个application
user模块的build.gradle
我们需要根据是否是module来确定当前模块的类型
if (isUserModule.toBoolean()){
apply plugin: 'com.android.library'
}else{
apply plugin: 'com.android.application'
}
根据类型加载不同的清单配置文件:
sourceSets {
main {
jniLibs.srcDirs = ['libs']
if (isUserModule.toBoolean()) {
manifest.srcFile 'src/main/release/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
}
}
}
其他模块依赖的时候:
如果类型为module,则依赖
if (isUserModule.toBoolean()) {
implementation project(':user')
}
这样一来,我们就可以方便的切换当前模块的类型了,也方便我们单独测试。
组件之间的通讯
关于组件之间的通讯,我采用的是使用阿里巴巴开源框架ARouter来解决,通过该框架我们可以实现不同模块之间的页面跳转,传值等。
ARouter Github
详细的使用方法直接查看官方文档即可,这里就不细说了。
建议:我们可以把路由配置信息放到公共库中,这样方便模块之前的跳转
实际上组件化开发的细节还有很多,说的再多都不如自己亲自写一写。
总得来说,组件化其实就是为了解耦以及实现代码复用,并且使代码更加的清晰,还没有试过组件化开发的建议试一下。
image本文在开源项目:https://github.com/Android-Alvin/Android-LearningNotes 中已收录,里面包含了Android组件化最全开源项目(美团App、得到App、支付宝App、微信App、蘑菇街App、有赞APP...)等,资源持续更新中...
网友评论