一、api与implementation的区别
从gradle-3.4
开始,compile
已经被api
与implementation
取代,官网也给出了三者之间的区别:
可以看出
implementation
可以让module
在编译时隐藏自己使用的依赖,但是在运行时这个依赖对所有模块是可见的。
api
与compile
一样,无法隐藏自己使用的依赖。
具体通过例子来看,下图为项目结构:
app
依赖模块mylibrary1
、mylibrary1
依赖模块mylibrary3
mylibrary1如下:
package com.example.mylibrary1;
public class MyClass1 {
public static String get(){
return "MyClass1";
}
}
mylibrary3如下:
package com.example.mylibrary3;
public class MyClass3 {
public static String get(){
return "MyClass33";
}
}
当mylibrary1 使用api依赖mylibrary3时,
api project(':mylibrary3')
在App中可以直接调用MyClass3类,也就是依赖可以传递。
package com.example.heshufan.learnapiandimp;
import com.example.mylibrary1.MyClass1;
import com.example.mylibrary3.MyClass3;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyClass1.get0();
MyClass3.get();
}
}
当mylibrary1使用implemention依赖mylibrary3时,
implementation project(':mylibrary3')
在App中,无法直接调用mylibrary3
换一句话说,就是api是对外的,就应该公开;而implementation是内部的实现,不应该公开出来。
从上面的例子可以看出,在多module中,implementation确实可以起到隐藏依赖的作用,网上很多的文章都只讲到了这点,那么这样做的目的是什么呢?其实这并不是Google设计implemention与api的目的,因为官方文档中说这样设计的目的在于减少build的时间,那么implemention是如何减少build time的呢?
二、implemention是如何减少build time
我们再新建一个module:mylibrary4
那么现在的项目依赖层级如下图所示
App--》mylibrary1 --》mylibrary3--》mylibrary4
1、如果3
使用api依赖4
,那么当4发生变化时,编译需要重新编译库4、3、1
;
2、如果3
使用implemention依赖4
,那么当4发生变化时,编译需要重新编译库4、3
,这个时候不需要编译库1,这样就可以节约build time;
为此我验证了两种依赖下项目的build time,每次重新编译前clean project,改变mylibrary4,然后rebuild project,再查看build time。可以看到api的build time比implemention多了1秒多,多次运行都多了1秒多,这还是在module比较小的情况下。如果包比较多,比较大,那么可以节约的时间是非常可观的。
三、远程依赖
现在在回过头来看一下依赖传递的问题,之前验证了使用implemention,app不能拿到MyClass3,这是在本地依赖的情况下,而现在的模块化开发多采用远程依赖的模式进行合作。那么如果采用maven远程依赖呢?
同样采用之前的例子,我们新建一个module :mylibrary2,将其上传到我们的本地maven
package com.example.mylibrary2;
public class MyClass2 {
public static String get(){
return "MyClass2";
}
}
最后在mylibrary1
中利用implemention依赖mylibrary2
//mylibrary1
implementation 'com.example:mylib2:1.0.0'
然后我们再将mylibrary1
上传到本地maven,然后在app
中远程依赖mylibrary1
//app
implementation 'com.example:mylib1:1.0.0'
也就是app远程implementation
mylibrary1,mylibrary1远程implemention
mylibrary2,
这时候app就可以直接拉到mylibrary2中的MyClass2类
而如果app本地implementation
mylibrary1,mylibrary1远程implemention
mylibrary2,这时候app则不能获取到mylibrary2中的myClass2类,依然起到了依赖隔离的作用。
由以上可以看到在全部远程依赖模式下,无论是api还是implemention都起不到依赖隔离的作用。
不过,在远程依赖模式下,依赖的一个模块如果版本发生变化,implemention与api的构建速度谁快谁慢还需要进一步研究。
综上,在多层次模块化(大于等于三层module)开发时,如果都是本地依赖,implementation相比api,主要优势在于减少build time。
如果只有两层module,api与implemention在build time上并无太大的差别。