补齐Android技能树 - 玩转Gradle(二) | 小册免费学(下)

简介: 在开始本节内容前,先来温习下几个关键词: Project(项目) → Gradle的构建 → 由一个或多个Project组成; Task(任务) → Gradle中的Project → 由一个或多个Task组成; Action(执行动作) → Gradle中的Task → 由一个或多个Action(函数/方法)按序组成;

可以看到好几种类型的 NotationConverter (依赖转换器):


// ① DependencyStringNotationConverter、DependencyMapNotationConverter 针对下面这种:
implementation(io.reactivex:rxandroid:1.2.1) {
    transitive = false
}
// ② DependencyFilesNotationConverter 针对下面这种:
implementation fileTree(dir:'libs', include:['*.jar'])
// ③ DependencyProjectNotationConverter 针对下面这种:
implementation project(":applemodule")
// ④ DependencyClasspathNotationConverter 针对claspath依赖的情况


所以就是利用各种类型的转换器,解析成各种不同的依赖,点开没个转换器,可以看到生成的依赖有这两种:SelfResolvingDependencyProjectDependency,打开前者:


网络异常,图片无法展示
|


注释写道:SelfResolvingDependency是独立于Repository,可以自解析的依赖。而后者则依赖于另一个项目:


网络异常,图片无法展示
|


那就来跟一跟吧~


3. ProjectDependency


跟下:DependencyProjectNotationConverter


网络异常,图片无法展示
|


跟下:DefaultProjectDependencyFactory → create()


网络异常,图片无法展示
|


instantiator.newInstance 用于实例化一个具有DSL特性的对象,此处返回了一个 ProjectDependency 实例,而另外一个create()方法,则传多了一个configuration名称。


关于依赖创建的过程先了解到这里,继续往下走涉及到artifacts的东西,后续章节在继续跟,先总结下:


  • ① DependencyHandler没有实现implementation、api这类方法(插件实现),利用MethodMissing机制间接调用这些方法;


  • ② 不同的依赖声明由不同的转换器进行转换,最后转换为SelfResolvingDependency和ProjectDependency两类依赖对象;


0x4、依赖冲突解决


来到实用解决问题环节,在模块化,或者依赖别人开源库的时候,依赖冲突问题总是避无可避~


① xxx Not Fount


  • 编译期:一般就是没有依赖正确的库导致;


  • 运行期:一般是使用了compileOnly导致某些库只在编译时依赖;


② Program type already present com.xxx.XXX


可以点击右侧的Gradle面板中的:Tasks → android → android dependencies 查看依赖树:


网络异常,图片无法展示
|


也可以执行下述命令将依赖树输出到特定文件中,方便检索:


./gradlew :app:dependencies > dependencies.txt
# 还可以分情况查看,如:
gradlew :module_base:dependencies --configuration api
# 查看指定库的依赖情况
/gradlew :app:dependencyInsight –dependency 指定库 –configuration compile
# 使用build scan分析依赖,生成HTML可读性和界面好康些~
./gradlew build --scan


接着就是根据编译报错结果定位到出问题的类,然后在依赖树中找到对应冲突的包了,接着是各类处理冲突的方法决策了。


③ 排除 & 禁用依赖传递


打开上面的依赖树,会发现有些依赖标注了 * 号,表示这个依赖被忽略了。


网络异常,图片无法展示
|


这就涉及到了 传递依赖,Gradle解析一个库时,会自动下载它的依赖库,以及此依赖库的依赖库(递归),然后再处理这些众多依赖库的版本匹配,就很容易出现依赖冲突的问题了。


一种简单的解决方法就是:引用依赖库时,排除某个引起冲突的依赖库,到他时不往下传递,如:


implementation("io.reactivex.rxjava2:rxandroid:2.1.1") {
    exclude(group = "io.reactivex.rxjava2", module = "rxjava")
    exclude(group = "io.reactivex.rxjava2")
}
// 全局配置排除
configurations {
  compile.exclude module: 'xxx'
  all*.exclude group:'xxx.xxx', module: 'XXX' 
}


另一种就是 禁用依赖传递,示例如下:


implementation("io.reactivex.rxjava2:rxandroid:2.1.1") {
    transitive = false
}
// 全局禁用
configurations.all {
    transitive = false
}


④ 强制使用当前版本


通过添加 isForce == true 强制使用特定版本,同一个模块多个版本都被force,以第一个为准:


dependencies {
    implementation("io.reactivex.rxjava2:rxjava:2.2.6") {
        isForce = true
    }
    implementation("io.reactivex.rxjava2:rxjava:2.2.10") {
        isForce = true
    }
}


上述的最终版本为2.2.6,force只作用于当前模块,不同模块间force相互独立,还要注意:模块force的某个依赖版本低于主模块的版本低,会发生编译错误,所以尽量不要在lib里force某个依赖的版本。


当然硬要这样搞也可以,主项目里再force一下(高低版本都可),或者是用下述代码替换依赖版本:


configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '27.1.1'//27.1.1为当前版本号
            }
        }
    }
}


目前了解到用过的解决方法就这些,有遗漏的欢迎在评论区补充,谢谢~


0x5、依赖规则


1. 多项目间共享依赖版本


新版Gradle支持 依赖和版本分开声明,以前我们在多项目中通过ext指定依赖库版本,然后子模块一个个依赖的方法可以用下述方式替代:


// 子项目version,专门用于管理版本,使用constraint共享版本
dependencies {
    constraints {
        implementation("io.reactivex.rxjava2:rxjava:2.2.0")
    }
}
// 其他子项目通过platform将子模块的所有依赖约束引入
dependencies {
    implementation(platform(project(":version")))
    // No version needed
    implementation("io.reactivex.rxjava2:rxjava")
}
// platform → require力度,想引入strictly力度,可以使用enforcedPlatform


2. 依赖约束力度


  • required → 我要依赖某个版本,但如果别的依赖提供了更高的版本则优先用更高的版本,默认。


  • strictly → 严格限制某个版本,常用于依赖版本降级,示例如下:


dependencies {
    implementation("io.reactivex.rxjava2:rxandroid:2.1.1") 
    implementation("io.reactivex.rxjava2:rxjava:2.2.0!!")
}


虽然rxandroid:2.1.1间接依赖了 rxjava:2.2.6, 但是由于 rxjava:2.2.0!! 严格约束的存在,最终决议为 rxjava:2.2.0,另外还支持范围区间约束,如[2.0.0, 2.2.0]!!,还有一点strictly相比起isForce无法降级直接依赖的组件版本。


  • prefer → 当没有更强的约束,则优先使用某个版本;


  • reject → 一般用于排除某个版本,比如有特定bug的版本;


参考文献:




相关文章
|
2月前
|
Android开发
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
|
2月前
|
Android开发
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
|
2月前
|
Java Android开发 Windows
玩转安卓之配置gradle-8.2.1
为安卓开发配置Gradle 8.2.1,包括下载和解压Gradle、配置环境变量、修改配置文件以增加国内镜像,以及在Android Studio中配置Gradle和JDK的过程。
90 0
玩转安卓之配置gradle-8.2.1
|
7月前
|
编解码 Java Android开发
Android技能树 — 屏幕适配小结,2024年最新android开发环境搭建教程
Android技能树 — 屏幕适配小结,2024年最新android开发环境搭建教程
|
4月前
|
Android开发
Android Studio: 解决Gradle sync failed 错误
本文介绍了解决Android Studio中出现的Gradle同步失败错误的步骤,包括从`gradle-wrapper.properties`文件中获取Gradle的下载链接,手动下载Gradle压缩包,并替换默认下载路径中的临时文件,然后重新触发Android Studio的"Try Again"来完成同步。
1492 0
Android Studio: 解决Gradle sync failed 错误
|
4月前
|
Java 开发工具 Maven
Flutter和Android中覆盖gradle中的repositories仓库地址
Flutter和Android中覆盖gradle中的repositories仓库地址
200 4
|
4月前
|
Android开发 Kotlin
The Android Gradle plugin supports only Kotlin Gradle plugin version 1.3.10 and higher
The Android Gradle plugin supports only Kotlin Gradle plugin version 1.3.10 and higher
96 3
|
4月前
|
Java 开发工具 Android开发
Android Studio利用Build.gradle导入Git commit ID、Git Branch、User等版本信息
本文介绍了在Android Studio项目中通过修改`build.gradle`脚本来自动获取并添加Git的commit ID、branch名称和用户信息到BuildConfig类中,从而实现在编译时将这些版本信息加入到APK中的方法。
85 0
|
4月前
|
IDE API 开发工具
与Android Gradle Plugin对应的Gradle版本和Android Studio版本
与Android Gradle Plugin对应的Gradle版本和Android Studio版本
470 0
|
4月前
|
Android开发
解决Android、Flutter编译时Gradle报错:javax.net.ssl.SSLException: Connection reset
解决Android、Flutter编译时Gradle报错:javax.net.ssl.SSLException: Connection reset
405 0