前言
implementation,api...,每次写的时候,都不好记住差别,都要重新查资料,实在麻烦,这也说明android studio有关这块的命名肯定不当,那么不容易记。
在此,需要搞清楚google为何这么搞,其动机是什么为了解决什么问题?
背景原因
其实追究其后面原因,是因为android studio要优化编译效率,解决依赖库的后期开发变更引起的一系列编译的效率问题。
例如有这么一个依赖:lib1依赖lib2,lib2依赖lib3,lib3依赖lib4 ....。
如果lib4某天内部进行了修改,那么lib3要不要重新编译?lib2,lib1呢?如果理论上不需要重新编译的,却因此而重新编译了,那么就是浪费时间,而android studio不够智能,无法检测到lib2、lib1要不要重新编译。这时候只能靠程序员来手工指定一些标志,然后android studio根据这些标志内部进行分析而决定哪些库需要重新编译。
原理
某个库,后期因为程序员改动而导致变化,分为两种:
1.对外接口不变;
2.对外接口变化了;
对于第1中情况,使用了这个库的其它库,都不需要重新编译,
对于第2中情况,所有引用了它的库都需要重新编译。
在实际使用中,引用的关系可能会更加复杂,例如下面的例子:
依赖关系:lib1->lib2->lib3->lib4。。。
这种依赖关系中,如果lib1不但使用lib2的接口,还通过lib2使用lib2依赖的lib3的接口,
那么lib3接口后期变化后lib1需要重新编译,
而如果lib1只是使用lib2的接口而不用lib3接口,则不需要重新编译。
android studio提出了库依赖关系声明,就是为了解决这种情况。
通过依赖关系声明,程序员可以表明lib2对lib3的引用仅仅是为了自己内部的实现而不对lib1提供接口,如此,编译系统就能在lib3后期修改的时候不再编译lib1。
依赖关系说明
发展到现在,android studio针对引用库的方式有好几种具体,参考下面的介绍。
- implementation
对库的引用,仅仅供自己内部实现,库的接口不对外公开。
例如lib2使用implementation的方式依赖引用lib3,如果lib1引用了lib2,那么lib1是无法使用lib2里面的lib3的接口,因为lib2使用了implementation。
- api
依赖的库不仅被自己用,其api接口还对外公开。所以,在编译时候,会一起打包。
例如lib2使用api的方式依赖lib3,lib1引用了lib2,则lib1就可以调用lib2中的lib3的接口。在编译打包lib2的时候,也会把lib3同时打包到lib2中。
- compileOnly
依赖的库仅仅用来编译,打包时候不参与。
- runtimeOnly
打包的时候会包括进去,不参与编译。
- testImplementation
测试才有效。
- debugImplementation
debug模式才用的implementation方式
- releaseImplementation
release模式才用的implementation方式
总结
implementation,意思就是你用这个库仅仅是为了自己内部的功能实现(implementation)!
api,意思就是,你除了自己用这个库,也把这个库对外公开,别人通过你,也能调用这个库的api接口!
最后:平时就用implementation,如果你要依赖的库里面有接口也想对外公开,那就用api。