引用其他project的module,根据参数自动配置依赖,repo管理多个 Project
Posted 薛瑄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了引用其他project的module,根据参数自动配置依赖,repo管理多个 Project相关的知识,希望对你有一定的参考价值。
前言
在开发中遇到这样一个问题,在工作的project(以下简称Project A)中,用到了Fragmentation(以下简称Project B) 库的三个module,这个库是我在维护,平时更改库中的一些bug,需要先使用一段时间,再推到github,并发布到jcenter, 所以在我的工作项目中,是直接使用本地的代码,没有使用jcenter去引用它。
这就遇到一个问题,在Project A 中改完 Project B的三个module,在等到发布的时候,就需要手动把代码拷贝一份到Project B中。如何能让这个过程简单点呢?
有小伙伴想到了,可以使用软连接,这样改完工作项目中的这三个module,就不再重复复制代码了。如果是多人协作开发,就不行了。
把Project B 这三个module ,分别使用git管理,整个工程项目使用repo 来管理,这样不管是哪个project 都可以方便的使用这三个module,但是这样对Project B 的改动较大。如果Project B 发布后,Project A 想通过jcenter 来引用这三个module,也不是很方便。(这种方式改造完,基本上就是现在江湖上组件化的结构)
于是在想,使用repo 来管理不同的Project,repo 本质是来管理多个git的,所以是project还是model,没有差别。这样可以来通过repo 来管理这个
另外两个问题:
在android studio中 一个project 如何使用另外一个project的module呢?
在本地没有 Project B,如何让Project A 自动通过jcenter来引用?
使用repo 来管理项目
repo 本质是来管理多个git的,所以无论是project 还是module,只要用git 来管理,那么他们就可以被repo管理
1、repo安装
折腾过Android 源码的同学,应该对这个很熟悉,可以直接去配置default.xml,然后按照自己的思路,就可以
创建bin 目录,并加入到环境变量
$ mkdir ~/bin
$ PATH=~/bin:$PATH
在bin 目录下,下载repo 工具
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
2、创建default.xml
repo 是用python开发的工具, 来管理不同项目的git,需要通过一个配置文件default.xml,来告诉他有哪些项目,远程地址是什么,本地路径是什么,review 等等
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<!-- -->
<remote name="github" fetch="https://github.com/JantHsueh" />
<remote name="aliyun" fetch="https://code.aliyun.com/cmoon" />
<default remote="aliyun" revision="master" sync-j="4"/>
<project name="cm-android.git" path="xw" />
<project name="Fragmentation.git" path="Fragmentation" remote="github"/>
</manifest>
remote 远程仓库地址配置,可以多个。
- name: 名字,也用于子仓库的 git remote 名称(.git/config 里的 remote)
- alias: 别名,可省略,建议设为 origin, 设置了那么子仓库的 git remote 即为此名,方便不同的 name 下可以最终设置生成相同的 remote 名称
- fetch: 仓库地址前缀,即 project 的仓库地址为: remote.fetch + project.name
- pushurl: 一般可省略,省略了则直接用 fetch
- review: Gerrit code review 的地址,如果没有用 Gerrit 则不需要配置(也就不能用 repo upload 命令了)
- revision: 使用此 remote 的默认分支
default配置默认远程仓库地址
- remote :它的值 是上面remote 标签 配置的name 值,表示远程仓库地址
- revision : 远程分支
- sync-j : 使用线程数
project
- name : 远程仓库的项目名,配合remote标签的fetch值,共同组成完整仓库地址:remote.fetch + project.name
- path:工程在本地的存储路径
- remote :它的值 是上面remote 标签 配置的name 值,表示远程仓库地址。如果没有配置,使用default中的配置
更多参数配置,查看官方文档repo Manifest Format
3、repo 初始化 和代码下载
# 初始化 repo default.xml 文件 会下载到 .repo/manifests/ 目录下
repo init -u https://github.com/anlory/manifest
# 根据配置,下载代码
repo sync
至此,repo就把这两个project 管理起来了,在项目中应该如何配置project直接的关系呢?
如何引用其他project?
default.xml 在 .repo/manifests/ 目录下 ,为了在project 中 能方便的通过 default.xml 控制项目,所以创建default.xml 软连接,放在project中,并加入到.gitignore 中
在setting.gradle 中,指定 module 的路径,这样就可以指定到其他project 中的 module
include ':app', ':mvvm'
//设置全局变量,在setting.gralde 和 build.gradle 中设置环境变量是不一样的
gradle.ext.localFragmentation = false
//在default.xml 中判断,是否有对应的project,如果有,repo sync 后 本地就有对应的代码,就配置使用本地工程代码
def manifest = new XmlParser().parse("$rootProject.projectDir/default.xml")
manifest.project.each
it.attributes().each k, v ->
// path 对应的值包含 Fragmentation 字段
if (k == 'path' && v.contains('Fragmentation'))
gradle.ext.localFragmentation = true
//指定Fragmentation工程的路径,在本示例中,两个工程的目录是同级的
def path = '../Fragmentation'
include ':Fragmentation'
project(':Fragmentation').projectDir = new File(path)
include ':fragmentation'
project(':fragmentation').projectDir = new File(path, 'fragmentation')
include ':fragmentation_core'
project(':fragmentation_core').projectDir = new File(path, 'fragmentation_core')
include ':fragmentation_swipeback'
project(':fragmentation_swipeback').projectDir = new File(path, 'fragmentation_swipeback')
gradle.ext.xx 和rootProject.ext.xx的用法差不多,只是变量存放的位置不同
- 在build.gradle 中配置全局变量 使用 rootProject.ext.
- 在setting.gradle中配置全局变量使用 gradle.ext
更多全局变量的使用,可参考这篇文章 gradle使用技巧之全局变量
如何根据参数,自动配置不同的依赖?
这个就很简单了,根据上面设置的全局变量来判断
dependencies
if (gradle.ext.localFragmentation)
api project(':fragmentation')
api project(':fragmentation_swipeback')
else
api 'me.xuexuan:fragmentationx:1.0.6'
api 'me.xuexuan:fragmentationx-swipeback:1.0.6'
当然可以有更多的玩法:
下面代码是参考这里的,需要引用哪个项目,从gradle.properties的配置中获取。
def moduleVersions = new Properties()
def moduleVersionsFile = new File("$project.projectDir/gradle.properties")
moduleVersions.load(moduleVersionsFile.newDataInputStream())
dependencies
def projects = moduleVersions.stringPropertyNames()
rootProject.subprojects.each
if (it.name != 'host')
implementation it
projects.remove(it.name)
projects.each
//为了方便引用,这里要求我们上传到 maven 的各模块的包遵循一定的规则,groupid 需要保持一致,
// artifactid 最好是以子 module 的 project.name 来命名,如果不是这样的规则,就需要自己修改 gradle 脚本啦
implementation "me.ailurus.repo:$it:$moduleVersions.getProperty(it)"
结语
在我看来,上面这种方式,算是project 之间的模块化,由于 project 可以多module的原因,很容易在多个project里 使用空 application 项目来打包apk
请点赞、收藏,感谢大家的支持,欢迎评论区提问、吐槽
Gradle Repo:一个能管理多个Git仓库,又能快速切换分支的Gradle插件
将数据从settings.gradle传递到build.gradle
Android Studio在同一个窗口中打开多个Project【附效果图附源码】
以上是关于引用其他project的module,根据参数自动配置依赖,repo管理多个 Project的主要内容,如果未能解决你的问题,请参考以下文章
Android Studio 生成aar包,并在其他项目中引用
Android Studio project和module的区别
Android Studio3.0 引用Module的本质和共享Module给其他Module