【转载】Android 接口的default 方法运行时报错AbstractMethodError

Android 接口的default 方法运行时报错AbstractMethodError - 掘金


【问题描述:接口default方法AbstractMethodError】

记录一个Android项目中遇到的问题,我们通过exclude方式重写了一个依赖,改用本地的实现,其中一个接口的default 方法,在运行时报错:AbstractMethodError,也就是没有找到这个default的实现。 

在这里插入图片描述

【定位原因:exclude导致d8不注入default方法的实现】

查看了exclude之后的apk里本地实现该default接口的class文件,发现Android d8工具实现了对Jave 8语言特性的兼容实现,实现方式是把接口的 default 方法生成了一个$-CC的合成类,所有继承这个接口的类里注入了一个合成方法,该方法调用了这个$-CC类里的实现。(编译过程

而我们exclude之后的apk里lib2实现该default接口的class文件,继承这个接口的类里没有注入这个合成方法,导致直接调用了接口的abstract定义,所以报出AbstractMethodError。

进一步实验发现,只要在依赖 lib2 时exclude了 lib1,即使app里重新依赖lib1,都会导致d8无法实现对 lib2 里default方法的注入。

所以问题的原因进一步需要定位:【为什么exclude之后,d8无法实现对 lib2 里default方法的注入?】

【解决方案:substitute】

笔者还没能分析出【为什么exclude之后,d8无法实现对 lib2 里default方法的注入?】这个问题,但是从另一个思路解决了这个问题,就是既然想把lib1的实现替换为本地的,可以建立一个子模块project(':local_lib1'),使用gradle的substitute语法来替换module lib1的依赖为project(':local_lib1'):

configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute module("com.harold.group:lib1") using project(":local_lib1") because "some reason"
    }
}

这正是gradle推荐使用substitute的场景:

One use case for dependency substitution is to use a locally developed version of a module in place of one that is downloaded from an external repository. This could be useful for testing a local, patched version of a dependency.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值