接入sdk库的几点心得体会
因为项目的特殊性,最近一直在往app工程里接入(升级)第三方sdk,并且app的少量基础控件也被其余项目组封装成了sdk来导入。在不停的sdk升级迭代过程中碰到了少量问题,记录一下为后续排查问题依据。
sdk本身内部可以依赖其余sdk库(假设为库A),此时库A不需要app显示导入,它在导入sdk时会自动导入进来(sdk发布时的aar文件有一个配对的pom.xml文件,他可以用来形容依赖),但可以通过
exclude
关键字取消对库A的自动导入。假如sdk本身依赖另一个库A,且app本身也对A库有导入依赖,这时就存在有两个地方对同一个库A的导入了。假如两处的版本号不一致的话,最终库A的什么版本是哪个呢?是以app的导入为准吗?还是以版本高的为准?结论是以版本号高的引用那个为准(打印依赖有向图可以看出)。
问题:明明我只是更新了sdk的版本,但最终的依赖库A的版本怎样也变了?因为库A的内容变了,那调用库A的代码就有可能存在不一致性了,特别是涉及到大版本升级时。这是可以通过依赖关系图来查看依赖的变化点和变化来源在哪里。另外一种情况:还是以上面的结论为基础,假设app依赖的库A版本比较高(最终以这个高版本为准),且这个高版本库A相比sdk依赖的低版本恰好删掉某一个API接口(比方是大版本更新),而sdk内部又恰好有调用这个删掉了的接口。
问题:此时是app竟然可以编译过!!! 只是会等到在运行时抛出找不到方法的异常。这怎样办?很严重,很隐秘的问题。
起因:针对这种情况刚开始还不能了解,都少了一个调用方法了为啥编译时没报错?后来想想也是正常的,这是由于app导入的sdk是以aar的形式引入的,而这个aar在sdk发布时就已经编译成字节码(class)了,所以此时编译app时编译器并不会再用javac去编译aar了(直接将aar的class类merge到app中),于是最终编译器没有检查调用关系的错误。
验证:即便使用exclude
将依赖库A排除依赖(最终的apk不包含库A的代码)也仍可以编译过。
今天碰到了这种情况,一时无法了解:
首先是一个sdk依赖的库A低版本(3.0.1)的接口:
//3.0.1public static Context build(Activity activity, boolean param1, boolean param2) { //...}
而后是app依赖的库A高版本(3.0.3)的接口:
//3.0.3public static Context build(Context context, boolean param1, boolean param2) { //...}
3.0.1版本与3.0.3版本的差异只是build()函数的第一个参数Activity
变为了Context
,但app更新了库A3.0.3版本后编译能通过,sdk内部却必现抛找不到方法异常:
java.lang.NoSuchMethodError: No static method build(Landroid/app/Activity;ZZ)Landroid/content/Context;
且我测试在app里调用这个build()方法又是正常的。为什么呢?起因就是上面说的(删掉了方法与修改了方法签名本质上是一样的),即便这里满足多态性(Context
是Activity
的基类)也不行。
- 在编写sdk时,暴露的API类和接口不宜轻易改动,否则可能会出现上述的依赖问题。废弃的方法和类可以使用注解
@Deprecated
标识起来,需要改动的接口使用方法重载的方式添加接口,而不是去改动接口。
查看app的依赖关系的命令:
./gradlew :app:dependencies
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 接入sdk库的几点心得体会