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

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

0x2、依赖规则


Gradle会声明每个依赖项的适用范围,可以理解为 分组,如:有些依赖在编译时用到,有些则在运行时用到,Gradle通过 Configuration 来表示这个范围(分组),不同的Configuration通过不同的name区分。


许多Gradle插件会预置一些Configuration添加到你的项目中,如Java插件:


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


有点懵,没关系,看下Android内置的这些Configuration你就懂了(2.x是废弃的):


// 对应2.x的 compile,既参与编译又参与打包
implementation → 当前模块依赖,但不向其他模块暴露此依赖,编译时只能在本模块访问;
api → 当前模块依赖,且向其他模块暴露此依赖,同compile;
举例区分下:
模块A、B,如果A依赖了Gson库,B依赖A,使用implementation,B用不了Gson,使用api,B可以使用Gson。
// 对应2.x的provided和apk,用的较少
compileOnly → 编译时有效,不会参与打包;
runtimeOnly → 运行时有效,不会参与编译;
annotationProcessor →  注解处理器依赖
testCompile → 对应2.x的testImplementation,只在单元测试代码的编译以及最终打包测试apk时有效;
debugCompile → 对应2.x的debugImplementation,只在debug模式的编译和最终的debug apk打包时有效;
releaseCompile → releaseImplementation,只在release的编译和最终的release apk打包时有效;
附:四种依赖方式
// ① 本地library依赖
implementation project(":mylibrary")  
// ② 本地二进制依赖
implementation files('libs/xxx.jar', 'libs/yyy.jar')    // 依赖特定库
implementation fileTree(dir: 'libs', include: ['*.jar']) // 依赖目录下的库
// ③ 远程二进制依赖
implementation('io.reactivex:rxandroid:1.2.1')
// ④ AAR包依赖
implementation(name: 'me.leolin:ShortcutBadger', ext: 'aar')    // 本地
implementation 'me.leolin:ShortcutBadger:1.1.17@aar'    // 远程


当然,你也可以自定义一个Configuration,示例如下:


allprojects {
    // 配置maven仓库地址
    repositories {
        maven { url "https://maven.aliyun.com/repository/jcenter" }
    }
}
// 定义一个名为myDependency的Configuration
configurations {
    myDependency
}
// 为自定义Configuration添加依赖
dependencies  {
    myDependency('io.reactivex:rxjava:1.1.9')
    myDependency('io.reactivex:rxandroid:1.2.1')
}
// 打印自定义Configuration下载依赖后的文件地址
task showMyDependency {
    println configurations.myDependency.asPath
}


终端键入:gradle showMyDependency,输出结果如下:


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


还可以调 extendsFrom 方法来继承另一个Configuration的所有dependencies,比如implementation就继承了compile。


最后还得提提两个标志,默认都为true:


  • canBeResolved:编译时依赖


  • canBeConsumed:运行时依赖


0x3、依赖创建的过程


Tips:跟源码了解下原理,不感兴趣可以直接跳过,不影响后续学习~


1. 依赖识别


build.gradle 处点开 dependencies,定位到了 Project 类:


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


看注释:传递的闭包由此Project的 DependencyHandler 执行,定位到此接口:


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


可以看到每个方法都返回 Dependency 实例,点开这个接口:


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


噢吼,接口定义了获取group、name、version的方法,回到 DependencyHandleradd() 方法,最多可传递三个参数:


implementation(io.reactivex:rxandroid:1.2.1) {
    transitive = false
}
Dependency add(String configurationName, Object dependencyNotation, Closure configureClosure);
// 参数一一对应:
implementation、io.reactivex:rxandroid:1.2.1、后面跟着的大括号(依赖配置闭包)


AS只能跟到这里,接着用VS Code打开Gradle的源码,全局搜下 implements DependencyHandler,定位到 DefaultDependencyHandler 类:


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


该类除了实现 DependencyHandler 接口外,还实现了一个**MethodMixIn** 接口:


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


在讲解这个接口前,我们先来了解下Groovy语言的两个特性:invokeMethodmethodMissing,先介绍下前者:


package groovy.reflect
class InvokeTest1 {
    def hello() {
        '执行Hello方法'
    }
    def invokeMethod(String name, Object args) {
        return "未知方法 $name(${args.join(',')})"
    }
    static main(args) {
        def it = new InvokeTest1()
        println it.hello()
        println it.foo("test", 28)
    }
}
// 运行输出:
// 执行Hello方法
// 未知方法 foo(test, 28)


对于一个对象的方法调用,类中有此方法就分发给此方法,如果不能分派,就调用invokeMethod方法,而methodMissing同样能实现上面的效果:


package groovy.reflect
class InvokeTest1 {
    def hello() {
        '执行Hello方法'
    }
    def methodMissing(String name, Object args) {
        return "未知方法 $name(${args.join(',')})"
    }
    static main(args) {
        def it = new InvokeTest1()
        println it.hello()
        println it.foo("test", 28)
    }
}


输出结果相同,而在Groovy中invokeMethod是用来 分发一个对象的所有方法 (已实现和未实现)的,要借助 GroovyInterceptable 接口。而methodMissing则只能 分发一个类未实现的方法,无论它是否实现了GroovyInterceptable接口。


总结下就是:invokeMethod管理所有方法,methodMissing只管理类所有的未实现方法!


弄懂后回到 MethodMixIn 接口,其实就是Gradle对methodMissing的封装,类想要实现这个特性,只需实现此接口,接口中定义了一个抽象方法 getAdditionalMethods() 返回一个 MethodAccess 对象:


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


定义了两个方法:判断某Method是否存在,动态执行Method,如出一辙,可以,跟下 getAdditionalMethods 重写处:


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


跟下哪里给 dynamicMethods 属性赋值:


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


跟下 DynamicAddDependencyMethods


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


参数个数判断,最后都调用到 dependencyAdder.add(),而 DependencyAdder 是一个内部接口,跟下哪里实现了:


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


实际上还是调用的 DefaultDependencyHandlerdoAdd() 方法:


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


判断dependencyNotation是否为Configuration对象,如果存在,就让当前的configuration对象继承dependencyNotation,即将添加到dependencyNotation的依赖都添加到configuration中。


2. 依赖创建


往下一点,可以看到 DefaultDependencyHandler 调用 create() 方法创建了一个 Dependency 的实例,跟下:


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


跟下:DefaultDependencyFactory → createDependency()


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


调用 dependencyNotationParser 实例的 parseNotation() 创建了 Dependency 实例,往上跟下:


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


构造方法里设置了这个参数,跟下哪里传入的:


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


跟下:DependencyNotationParser → parser()


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



相关文章
|
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