内容简介:书接上文,上回提到 B 站Android团队为了解决组件化后协作上的问题,已经采用了国内实践大仓的团队少之又少,更别提 Android 的大仓了,几乎没有来自其它团队的可借鉴经验。在这条路上,我们可以算作先行者。本文粗陋,文中所列思路首先回顾一下 Android 项目的组织方式。自从13年开始官方逐渐迁移到
书接上文,上回提到 B 站Android团队为了解决组件化后协作上的问题,已经采用了 大仓(monorepo)
的方案来组织代码。
国内实践大仓的团队少之又少,更别提 Android 的大仓了,几乎没有来自其它团队的可借鉴经验。在这条路上,我们可以算作先行者。本文粗陋,文中所列思路 不可能 适用所有团队,仅给同样想实践Android 大仓的人些许启发。
一个标准的 Gradle 项目
首先回顾一下 Android 项目的组织方式。自从13年开始官方逐渐迁移到 Android Studio 做为 IDE 后, Android 项目的开发和编译就绑在 Gradle 上了。
一个 标准的 Gradle 项目
结构如下所示:
MyApp/ ├── build.gradle ├── settings.gradle ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradle.properties └── app ├── build.gradle └── src └── main ├── java ├── res └── AndroidManifest.xml
通常,会有多个Gradle Module存在:
MyApp/ ├── build.gradle ├── settings.gradle ├── app │ ├── build.gradle │ └── src ├── lib1 │ ├── build.gradle │ └── src └── lib2 ├── build.gradle └── src
其中 settings.gradle
会注册所有的 Module
include ':app', ':lib1', ':lib2'
多仓库
随业务的扩张,Module 数量会越来越多。遵循多数人实践过的组件化的思路,按业务分仓库存放便理所当然:
android group/ ├── MyApp/ │ ├── build.gradle │ └── settings.gradle ├── app1/ │ ├── build.gradle │ └── settings.gradle ├── app2/ │ ├── build.gradle │ └── settings.gradle └── libs/ ├── build.gradle └── settings.gradle
每个仓库都是一个 标准 Gradle 项目
,通过
publishing
插件将module 都上传 aar(或者jar)到 maven私服(如 nexus
)上,再在 MyApp/build.gradle
中以 maven 组件的形式依赖它们,最终打包成apk:
repositories { maven { name = "myRepo" url = "http://myrepo.example.com/android" } } dependencies { implementation 'com.example.android:app-a:1.0.0' implementation 'com.example.android:app-b:1.0.0' implementation 'com.example.android:lib-a:1.1.0' }
此时的代码组织方式便是上文中所述的多仓库形态(可能许多团队正处于当前阶段)。
多仓到大仓
那么,如何既能快速搭建出适用于 Android 的大仓,又能不影响当前的团队协作流程,还要尽量避免迁移带来的开发效率降低?
经过一段时间的深入研究 Gradle API,终于找到一个简单快速的可行方案—— composite builds 。
上面说过,其实每个仓库都是按业务分离的标准的 Gradle 项目,那么就可以通过Gradle 官方提供的一个直接引入其它项目的API—— includeBuild ——快速将所有仓库组织起来。
在 MyApp/settings.gradle
中直接引入其它 Gradle 项目:
includeBuild '../app1' includeBuild '../app2' includeBuild '../libs'
另外比较令人惊喜的是,如Gradle 官方所说, includeBuild
会自动替换依赖 com.example.android:app-a
为有对应声明的module,如 project(:app1:app-a)
。这样仍然可以用原有的依赖写法,什么都不用改,基本没有迁移工作量。
具体示例可以见官方示例项目: https://github.com/gradle/gradle/tree/master/subprojects/docs/src/samples/compositeBuilds/hierarchical-multirepo
而且,使用 includeBuild
能保留当前的开发流程不变,每个模块仍发布到 maven 上,不破坏既有协作流程。各个业务的开发,通过Android Studio 打开自己项目的目录即可,可以说几乎没有开发效率的影响。
解决了各个项目合并问题,另外一个就是要保证大仓的可维护性。
上文讲过,依然沿用之前分层的方式,按约定的文件夹组织:
<root dir> ├── build.gradle ├── settings.gradle ├── app/ │ ├── app-a │ │ ├── src │ │ └── build.gradle │ ├── app-b │ │ ├── src │ │ └── build.gradle │ ├── build.gradle │ └── settings.gradle │ ├── common/ │ ├── common-a │ │ ├── src │ │ └── build.gradle │ ├── build.gradle │ └── settings.gradle │ ├── framework/ │ ├── lib-a │ │ ├── src │ │ └── build.gradle │ ├── build.gradle │ └── settings.gradle │ └── MyApp ├── src └── build.gradle
各个业务方的代码只需要按层级对号入座即可。
对号入座的方式有很多种,最简单的便是直接拷贝项目到对应目录,而如果要保留原仓库的提交记录,则可以使用 git filter-branch 和 git update-index 等命令(略过不表╮( ̄▽ ̄)╭)。
收敛合并权限
人总是会犯错的,为了不让近百名开发成员在一个仓库里打架,我们需要在 gitlab 权限分配的基础上,通过API实现自动化的方式来合并代码。
每个文件夹(或者模块)可以添加一个配置文件,如 OWNERS ,业务团队自己分配 owner和reviewer。
<root dir> ├── app │ ├── OWNERS │ └── app-a │ └── OWNERS ├── common │ ├── OWNERS │ └── common-a │ └── OWNERS ├── framework │ ├── OWNERS │ └── lib-a │ └── OWNERS └── MyApp └── OWNERS
通过gitlab webhook及note api来实现一个自动化工具:
当开发人员提交一个新的 Merge Reqeust 时,工具找到有变更文件夹的对应 owner 及 reviewer,提醒他来review 和操作合并;当他在MR中提交merge指令时,由自动化 工具 执行合并操作。
综述
includeBuild
通过上述两个步骤,便打造了一个大仓雏形。
关于大仓,本文只简单描述了一下方案大致思路,行文粗糙,希望对想实践大仓的你有所帮助,如有疑问欢迎评论留言。未来可能会有更多文章展开详述细节(当然如果无人问津的话就… >﹏<
以上所述就是小编给大家介绍的《如何简单快速搭建 Android 大仓》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- [译]使用Redis Bitamp简单快速实时计算指标
- Jboot 2.2.0 发布,分布式开发更加简单快速
- Jboot 2.2.1 发布,分布式开发更加简单快速
- Jboot 2.2.2 发布,分布式开发更加简单快速
- 如何简单快速的将纸质文件扫描成可编辑格式?
- 谷歌开源Neural Tangents:简单快速训练无限宽度神经网络
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。