参考文章: https://www.shangmayuan.com/a/cd9e30407e13423ca82322d4.html https://juejin.cn/post/6844904176250519565
在AS项目中,常常引用多个Module,多人参与项目开发,这种背景下,时常遇到版本冲突问题,出现不一样的compileSdkVersion等,致使包体变大,项目运行时间变长,因此将依赖版本统一是一个项目优化的必经之路。
你可能遇到这样的问题 在架构设计阶段,你的依赖库是这样的
同事并行开发后,合并代码后,变成了这样
哈哈哈,这就是没作好依赖管理的后果!下面介绍三种依赖管理方式。若是对前两种已经很熟悉了,能够直接跳转看第三种Composing builds,推荐使用第三种。
咱们在使用Groovy语言构建项目的时候,抽取config.gradle做为全局的变量控制,使用ext扩展函数来统一配置依赖,以下:
ext {
android = [
compileSdkVersion: 29,
buildToolsVersion: "29",
minSdkVersion : 17,
targetSdkVersion : 26,
versionCode : 102,
versionName : "1.0.2"
]
version = [
appcompatVersion : "1.1.0",
coreKtxVersion : "1.2.0",
supportLibraryVersion : "28.0.0",
androidTestVersion : "3.0.1",
junitVersion : "4.12",
glideVersion : "4.11.0",
okhttpVersion : "3.11.0",
retrofitVersion : "2.3.0",
constraintLayoutVersion: "1.1.3",
gsonVersion : "2.7",
rxjavaVersion : "2.2.2",
rxandroidVersion : "2.1.0",
..........省略...........
]
dependencies = [
//base
"constraintLayout" : "androidx.constraintlayout:constraintlayout:${version["constraintLayoutVersion"]}",
"appcompat" : "androidx.appcompat:appcompat:${version["appcompatVersion"]}",
"coreKtx" : "androidx.core:core-ktx:${version["coreKtxVersion"]}",
"material" : "com.google.android.material:material:1.2.1",
//multidex
"multidex" : "com.android.support:multidex:${version["multidexVersion"]}",
//okhttp
"okhttp" : "com.squareup.okhttp3:okhttp:${version["okhttpVersion"]}",
"logging-interceptor" : "com.squareup.okhttp3:logging-interceptor:${version["okhttpVersion"]}",
//retrofit
"retrofit" : "com.squareup.retrofit2:retrofit:${version["retrofitVersion"]}",
"converter-gson" : "com.squareup.retrofit2:converter-gson:${version["retrofitVersion"]}",
"adapter-rxjava2" : "com.squareup.retrofit2:adapter-rxjava2:${version["retrofitVersion"]}",
"converter-scalars" : "com.squareup.retrofit2:converter-scalars:${version["retrofitVersion"]}",
..........省略...........
]
}
依赖写完以后,在root路径下的build.gradle
添加apply from: "config.gradle"
而后在须要依赖的module下的build.gradle中web
dependencies {
...
// Retrofit + okhttp 相关的依赖包
api rootProject.ext.dependencies["retrofit"]
...
}
以上就是Groovy ext扩展函数的依赖管理方式,此方式能够作到版本依赖,可是最大的缺点就是没法跟踪代码,想要找到上面示例代码中的rootProject.ext.dependencies["retrofit"]
这个依赖,须要手动切到config.gradle去搜索查找,可读性不好。
参考文档: https://handstandsam.com/2018/02/11/kotlin-buildsrc-for-better-gradle-dependency-management/
当运行 Gradle 时会检查项目中是否存在一个名为 buildSrc 的目录。然后 Gradle 会自动编译并测试这段代码,并将其放入构建脚本的类路径中。
对于多项目构建,只能有一个 buildSrc 目录,该目录必须位于根项目目录中。
buildSrc 是 Gradle 项目根目录下的一个目录,它可以包含我们的构建逻辑,与脚本插件相比,buildSrc 应该是首选,因为它更易于维护、重构和测试代码
buildSrc 这种方式,在最近几年是非常流行的,因为它有以下优点:
buildSrc 依赖更新将从新构建整个项目,项目越大,从新构建的时间就越长,形成没必要要的时间浪费
buildSrc 的文件夹
, 名字必须是 buildSrc,因为运行 Gradle 时会检查项目中是否存在一个名为 buildSrc 的目录
build.gradle.kts
的文件,添加以下内容plugins {
`kotlin-dsl`
}
repositories{
jcenter()
}
buildSrc/src/main/java/包名/
目录下新建 Deps.kt 文件
,添加以下内容object Versions {
......
val appcompat = "1.1.0"
......
}
object Deps {
......
val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
......
}
app模块
引入包import me.jiatao.plugin.*
implementation Deps.appcompat
Composing builds只是包含其余构建的构建。 在许多方面,复合构建相似于Gradle多项目构建,不一样之处在于,它包括完整的构建,而不是包括单个项目。
使用这种方式的优势有: 1.支持单向跟踪 2.自动补全 3.依赖更新时,不会从新构建整个项目,这是相比buildSrc最大的优势。
新建VersionPlugin模块,由于Composing builds可以放置在项目外,所以我们可以把VersionPlugin的目录与项目同级,这样就可以供多项目同时使用。
在新建的module下的build.gradle文件中,添加以下代码:
buildscript {
repositories {
jcenter()
}
dependencies {
// 因为使用的 Kotlin 需要需要添加 Kotlin 插件
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
}
}
apply plugin: 'kotlin'
apply plugin: 'java-gradle-plugin'
repositories {
// 需要添加 jcenter 否则会提示找不到 gradlePlugin
jcenter()
}
dependencies {
implementation gradleApi()
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21"
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
gradlePlugin {
plugins {
version {
// 在 app 模块需要通过 id 引用这个插件
id = 'me.jiatao.plugin'
// 实现这个插件的类的路径
implementationClass = 'me.jiatao.plugin.VersionPlugin'
}
}
}
当前代码可以和buildSrc方式公用
VersionPlugin/src/main/java/包名/
目录下新建 DependencyManager.kt
文件,添加你的依赖配置,如:package me.jiatao.plugin
object Versions {
//AndroidX
const val activity = "1.3.0"
const val appcompat = "1.3.1"
const val coreKtx = "1.6.0"
const val constraintLayout = "2.1.0"
const val material = "1.4.0"
const val cardView = "1.0.0"
const val recyclerview = "1.0.0"
const val fragment = "1.3.6"
//jetpack
const val lifecycle = "2.3.1"
const val paging = "3.0.1"
const val work = "2.5.0"
const val room = "2.3.0"
//network
const val retrofit = "2.9.0"
const val okhttpLogging = "4.9.0"
//kotlin
const val kotlin = "1.5.21"
const val kotlinCoroutinesCore = "1.5.0"
const val kotlinCoroutinesAndroid = "1.5.0"
//依赖注入库
const val hilt = "2.38.1"
//kotlin辅助库,暂不使用
const val koin = "2.1.5"
const val anko = "0.10.8"
//test
const val junit = "4.12"
const val junitExt = "1.1.3"
const val espressoCore = "3.4.0"
//log
const val timber = "4.7.1"
//dataBinding helper
const val dhlBinding = "1.1.3"
}
object Kotlin {
const val plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}"
//const val stdlibJdk7 = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}"
const val stdlibJdk8 = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Versions.kotlin}"
const val test = "org.jetbrains.kotlin:kotlin-test-junit:${Versions.kotlin}"
const val coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutinesCore}"
const val coroutinesAndroid = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.kotlinCoroutinesAndroid}"
}
object AndroidX {
const val activity = "androidx.activity:activity-ktx:${Versions.activity}"
const val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
const val coreKtx = "androidx.core:core-ktx:${Versions.coreKtx}"
const val constraintLayout = "androidx.constraintlayout:constraintlayout:${Versions.constraintLayout}"
const val material = "com.google.android.material:material:${Versions.material}"
const val cardView = "androidx.cardview:cardview:${Versions.cardView}"
const val recyclerview = "androidx.recyclerview:recyclerview:${Versions.recyclerview}"
//jetpack
const val lifecycleRuntime = "androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifecycle}"
const val lifecycle = "androidx.lifecycle:lifecycle-livedata-ktx:${Versions.lifecycle}"
const val viewModel = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifecycle}"
const val viewModelSavedState = "androidx.lifecycle:lifecycle-viewmodel-savedstate:${Versions.lifecycle}"
//Paging3
const val pagingRuntime = "androidx.paging:paging-runtime:${Versions.paging}"
//Android WorkManager
const val workRuntime = "androidx.work:work-runtime:${Versions.work}"
const val workTesting = "androidx.work:work-testing:${Versions.work}"
}
object Room {
//使用kapt引入
const val compiler = "androidx.room:room-compiler:${Versions.room}"
const val runtime = "androidx.room:room-runtime:${Versions.room}"
const val ktx = "androidx.room:room-ktx:${Versions.room}"
const val rxjava2 = "androidx.room:room-rxjava2:${Versions.room}"
const val testing = "androidx.room:room-testing:${Versions.room}"
}
object Fragment {
const val runtime = "androidx.fragment:fragment:${Versions.fragment}"
const val runtimeKtx = "androidx.fragment:fragment-ktx:${Versions.fragment}"
const val testing = "androidx.fragment:fragment-testing:${Versions.fragment}"
}
object Retrofit {
const val runtime = "com.squareup.retrofit2:retrofit:${Versions.retrofit}"
const val gson = "com.squareup.retrofit2:converter-gson:${Versions.retrofit}"
const val mock = "com.squareup.retrofit2:retrofit-mock:${Versions.retrofit}"
const val logging = "com.squareup.okhttp3:logging-interceptor:${Versions.okhttpLogging}"
}
object Hilt {
const val plugin ="com.google.dagger:hilt-android-gradle-plugin:${Versions.hilt}"
//使用kapt引入
const val compiler = "com.google.dagger:hilt-compiler:${Versions.hilt}"
const val hilt = "com.google.dagger:hilt-android:${Versions.hilt}"
}
object Koin {
const val core = "org.koin:koin-core:${Versions.koin}"
const val androidCore = "org.koin:koin-android:${Versions.koin}"
const val viewModel = "org.koin:koin-androidx-viewmodel:${Versions.koin}"
const val androidScope = "org.koin:koin-android-scope:$${Versions.koin}"
}
object Anko {
const val common = "org.jetbrains.anko:anko-common:${Versions.anko}"
const val sqlite = "org.jetbrains.anko:anko-sqlite:${Versions.anko}"
const val coroutines = "org.jetbrains.anko:anko-coroutines:${Versions.anko}"
const val design = "org.jetbrains.anko:anko-design:${Versions.anko}" // For SnackBars
}
object Depend {
const val junit = "junit:junit:${Versions.junit}"
const val androidTestJunit = "androidx.test.ext:junit:${Versions.junitExt}"
const val espressoCore = "androidx.test.espresso:espresso-core:${Versions.espressoCore}"
//日志输出
const val timber = "com.jakewharton.timber:timber:${Versions.timber}"
//简化dataBinding的库
const val jDataBinding = "com.hi-dhl:binding:${Versions.dhlBinding}"
}
BuildConfig.kt
用于管理项目配置package me.jiatao.plugin
object BuildConfig {
const val compileSdkVersion = 30
const val targetSdkVersion = 30
const val minSdkVersion = 21
const val buildToolsVersion = "30.0.3"
const val versionCode = 1
const val versionName = "1.0.0"
}
.在 VersionPlugin/src/main/java/包名/
目录下新建 VersionPlugin.kt,实现Plugin接口,以下:
class VersionPlugin : Plugin<Project> {
override fun apply(project: Project) {
}
companion object {
}
}
......
includeBuild("../VersionPlugin")
include ':app'
......
buildscript {
......
}
/**
* 如果在多项目构建中,可能想把插件应用到子项目中,apply false 来告诉 Gradle 不要应用插件
* plugins {} 默认的行为是解析和应用插件
*/
plugins {
// 这个id就是在 VersionPlugin/build.gradle 文件内定义的id
id "me.jiatao.plugin" apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
/**
* 默认在所有子项目中,引入公用插件
*/
subprojects { subproject ->
// 默认应用所有子项目中
apply plugin: 'me.jiatao.plugin'
// 如果想应用到某个子项目中,可以通过 subproject.name 来判断应用在哪个子项目中
// subproject.name 是你子项目的名字,示例如下
// 官方文档地址:https://guides.gradle.org/creating-multi-project-builds/#add_documentation
if (subproject.name == "app") {
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
}
}
更新app模块下的build.gradle,导入文件
import me.jiatao.plugin.*
替换类
......
implementation AndroidX.coreKtx
implementation AndroidX.appcompat
implementation AndroidX.material
......
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。