组件化一定逃不过各个组件/模块通过依赖的方式组装成一个app的结构,所以首先就要学会如何上传模块到maven仓库。
建立Maven仓库
Nexus配置
下载地址:www.sonatype.com/nexus/repos…
下载后解压文件到任意目录,进入到 bin 目录下,比如我自己的路径就是 /Users/用户名/Downloads/应用/nexus-3.29.2-02-mac/nexus-3.29.2-02/bin,然后在该目录下打开命令窗口输入 ./nexus start,这样nexus就启动起来了,在浏览器那输入 http://127.0.0.1:8081 就是可视化工作台了。登录账号是admin,默认密码在 /Users/用户名/Downloads/应用/sonatype-work/nexus/admin.password 文件内,当然首次登录后你最好设置一个自己容易记的密码。
创建Repository
可以使用自带的maven-releases和maven-snapshots,自定义仓库的话根据箭头标识按顺序点击 Create Repository,创建时注意选择 maven2 hosted 即可,最好创建snapshot和release版本。
snapshot和release区别: snapshot表示快照版本,一般用于开发阶段,maven会自动识别版本号后带-SNAPSHOT,这样我们不需要更改版本号就可以让依赖方更新库,开发时会经常上传每次更改版本号的话没必要。release是发布版本, 在发布的时候版本号都需要增加,否则依赖方无法更新库(除非把缓存都删除了重新下载依赖库)。
gradle已有的上传任务
单独创建一个 upload-aar.gradle 文件:
apply plugin: 'maven'
def POM_VERSION = '1.0.0'
def POM_ARTIFACT_ID = 'biz_home'
def POM_GROUP_ID = 'com.sun.biz'
def POM_PACKAGING = 'aar'
def USERNAME = 'admin'
def PASSWORD = 'admin123'
def REPOSITORY_URL = 'http://localhost:8081/repository/sun/'
def REPOSITORY_URL_SNAPSHOT = 'http://localhost:8081/repository/sun-snapshot/'
def getPomVersion(pomVersion) {
String version = pomVersion
// gradle.properties内声明
if(isSnapshot.toBoolean()) {
version += "-SNAPSHOT"
}
return version
}
uploadArchives {
repositories {
mavenDeployer {
snapshotRepository(url: REPOSITORY_URL_SNAPSHOT) {
authentication(userName: USERNAME, password: PASSWORD)
}
repository(url: REPOSITORY_URL) {
authentication(userName: USERNAME, password: PASSWORD)
}
pom.project {
version getPomVersion(POM_VERSION)
artifactId POM_ARTIFACT_ID
groupId POM_GROUP_ID
packaging POM_PACKAGING
}
}
}
}
上传模板基本可以套用,这里可以看到gradle.properties内声明了一个变量用来控制是否是快照版本:
isSnapshot = true
如果是那么就要加上后缀1.0.0-SNAPSHOT,maven就会自动识别这个是快照版本。当快照版本上传时会使用 snapshotRepository 上传,正式版本则用 repository 来上传,因此可以指定不同的url。我们可以把相关联的库放到同一个groupId下,artifactId 必须是唯一的。
使用这个上传功能需要把 upload-aar.gradle 引入到模块的build.gradle内:
apply from: 'upload-aar.gradle'
同步gradle后,可以用命令行的方式上传:
./gradlew uploadArchives
也可以用AndroidStudio自带视图去执行任务:
最后按上面的例子,使用者通过依赖快照版本的路径应该是这样的:
implementation 'com.sun.biz.biz_home:1.0.0-SNAPSHOT'
同时需要在根目录的build.gradle配置加上maven仓库的url:
buildscript {
repository {
maven {url 'http://127.0.0.1:8081/repository/sun-snapshot/'}
}
}
完整的上传逻辑已经完成了,但是你会发现download下来的库没有源码,所以我们需要把源码的上传加入到 upload-aar.gradle内即可:
// 生成javadoc.jar
task androidJavadocsJar(type: Jar) {
// 指定文档名称
classifier = 'javadoc'
from android.sourceSets.main.java.srcDirs
}
// 打包main目录下代码和资源的task,生成sources.jar
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
//配置需要上传到maven仓库的文件
artifacts {
archives androidSourcesJar
archives androidJavadocsJar
}
自定义上传插件
gradle自带的上传任务已经足够满足一些小项目。当遇到大项目的组件化时,你可能会有几十个工程,并且一个工程中可能存在多个模块(如一个实现层、一个接口层),如果使用自带上传任务,那么需要每一个模块都放一份 upload-aar.gradle 文件,会有相当多的重复性工作,并且上传时也要多次上传(实现层上传一次,接口层上传一次)。这个时候需要自定义上传插件为了解决效率应运而生了。
先思考下这个插件是为了解决什么问题:
- 多工程复用,只需要依赖一个plugin就能使用。
- 工程内多模块执行一次任务就能全部上传(这里可能有疑问,为啥我只改了实现层代码还需要把接口层又上传一遍,不是做无用功了吗?其实一个工程的所有相关模块最好版本都是保持一致的,在大项目里你就知道这样的版本管理有多省心了)。
- 后续根据需求可以在上传之前做其他的校验,比如校验是否合并过主分支的代码等逻辑,如果不通过就终止上传。
对于gradle plugin的开发没有太多的文章去讲解某个插件怎么做之类的,主要还是参考 gradle plugin官网。相信逻辑上并不会很难,只是需要查找和熟悉各种api。
大致说下开发这个上传插件的思路:
- 开发gradle plugin的模板代码,提供插件名、函数名等
- 建立上传模型,除了必要的pomGroupId、pomArtifactId、pomVersion等字段,还需要一个order作为模块上传的顺序。
- 遍历project里的所有子模块并根据order排序,发现和配置一样的模块名,执行 maven 自带的 uploadArchives 函数,uploadArchives的变量就是我们建立的上传模型。给每个模块新建一个任务,这个任务依赖于 uploadArchives,最后用dependsOn指定任务执行顺序。
项目源码:GradleLearning
版本依赖
每个模块版本上传之后,最终会集成在壳工程里,最简单的壳工程应该只有 application 用来初始化某些东西。其他的都在build.gradle内依赖模块,以本系列的举例:
dependencies {
implementation 'com.sun.biz:biz_home:1.0.0'
implementation 'com.sun.biz:biz_me:1.0.0'
implementation 'com.sun.biz:biz_msg:1.0.0'
implementation 'com.sun.biz:export_biz_home:1.0.0'
implementation 'com.sun.biz:export_biz_me:1.0.0'
implementation 'com.sun.biz:export_biz_msg:1.0.0'
implementation 'com.sun.fun:fun_share:1.0.0'
implementation 'com.sun.fun:export_fun_share:1.0.0'
implementation 'com.sun.module:module_base:1.0.0'
implementation 'com.sun.module:module_common:1.0.0'
}
各种基础模块、业务模块的接口层和实现层都会依赖,而模块之间依赖则只依赖接口层即可。debug和release可区分snapshot版本。