先来看下gradle依赖的几种常见的关键词
新配置 | 已弃用配置 | 行为 | 本Module | 上层Module |
implementation | compile | 依赖项在编译时对模块可用,并且仅在运行时对模块的消费者可用。 对于大型多项目构建,使用 implementation 而不是 api /compile 可以显著缩短构建时间,因为它可以减少构建系统需要重新编译的项目量。 大多数应用和测试模块都应使用此配置。 | 编译&运行 | 运行 |
api | compile | 依赖项在编译时对模块可用,并且在编译时和运行时还对模块的消费者可用。 此配置的行为类似于 compile (现在已弃用),一般情况下,您应当仅在库模块中使用它。 应用模块应使用 implementation ,除非您想要将其 API 公开给单独的测试模块。 | 编译&运行 | 编译&运行 |
compileOnly | provided | 依赖项仅在编译时对模块可用,并且在编译或运行时对其消费者不可用。 此配置的行为类似于 provided (现在已弃用)。 | 编译 | - |
runtimeOnly | apk | 依赖项仅在运行时对模块及其消费者可用。 此配置的行为类似于 apk (现在已弃用)。 | 运行 | 运行 |
上表中,“编译”表示在本Module中编译过程时可以使用lib,"运行"表示在本Module在运行时可以使用lib。举例,A依赖B,B依赖C,在B中使用“implementation”依赖时“implementation 'com.google.code.gson:gson:2.6.2'”,B可以在编译和运行时都可以使用gson库中代码。但是,A只能在运行时才能使用gson库中的代码,编译时,也就是写代码的时候,是无法引用到gson库中的代码的。
上述的依赖传递仅适用于远程依赖,例如“implementation 'com.example.android:app-magic:12.3'”。但是对于本地aar依赖,比如“implementation files('libs/foo.jar', 'libs/bar.jar')”是不一样的。
在Module中使用了implementation关键词依赖了远程库,比如“implementation 'com.google.code.gson:gson:2.6.2'”,然后我把Module打包成aar,依赖到其他的Module中,运行的时候会出现"java.lang.NoClassDefFoundError:gson"的异常。这是不是很奇怪,我明明已经把库依赖进去了,但是打成aar之后,就报错。在当前Module运行时没有这个报错。原因是,远程依赖是存放在xxx.pom文件中的,而打包成aar后已经不带有这些特性。所以当然是无法传递这个依赖了。但是如果是jar/aar本地依赖进来的,那是被打进aar内部的,所以还是可以使用的。