implementation、api与多模块依赖

自从gradle升级3.+版本后,gradle原来的依赖方法全部都被替换了,之前的compile替换成了implementation和api,新建工程时发现gradle默认使用的也是implementation。而最近使用多模块依赖时,发现app模块使用implementation依赖子模块时,无法直接访问子模块依赖的库,于是查了下文档:

 

从文档可以看出,当使用a模块implementation方法依赖某第三方库h时,在编译过程中其他模块是无法访问a模块中h库的接口,但是在运行期间是可供其他模块使用。而api方法则是可以在编译和运行期间都可以将a模块的h库的接口暴露给其他模块,就如同原来compile方法,这样说可能有点绕,直接上例子:

新建一个项目,项目结构如图:

library1的依赖如下:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'

    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
}

app依赖library1,在app中,是无法访问到Retrofit的库的,

如图,直接报红,将library1的 implementation改成api,重新编译,报红消失

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'

    api 'com.squareup.retrofit2:retrofit:2.4.0'
}

那么问题来了,为什么要有implementation这种设计呢,回头看上面的文档,当使用api(compile)方法依赖模块a,当a有对外接口改动时,所有(直接或间接)依赖了模块a的模块gradle都会重新编译,这就明显增加了编译时间,而使用了 implementation就很好的解决了这个问题。

举个例子,假如一个app有如下依赖结构:

当模块A内部代码(不涉及到对外接口)修改时,Gradle只对A模块重新编译,不会对其他模块做编译。而当模块A的外接口做出修改时,此时直接依赖模块A的模块B和C也需要重新编译,假如api(compile)方法依赖,那么A的接口在D和E甚至APP中都能访问A的接口,那么就有可能需要根据模块A接口的修改而做出一些代码的改动,gradle为了保险起见,也会对间接引用的D、E和APP重新编译,这无疑增加了gradle的编译时间。

而使用implementation方法时,模块A只对直接引用它的模块C和B开放,对于间接引用的模块D和E是无法访问A的,所以当A接口改变时,只有直接引用它的模块才会重新编译,这在一定程度上节省了编译时间。

所以,在项目依赖时尽量使用implementation方法,这也是官方推荐的,当且仅当你需要将引用的模块的接口对外暴露出去时,才使用api方法。

 

猜你喜欢

转载自blog.csdn.net/u011598031/article/details/82152071