kotlin - 在用 Kotlin 编写的 Android 库的公共 API 中处理 R8 + JvmStatic Annotation + Lambda
问题描述
首先,请注意,我不期待why do you want to obfuscate library
评论。这是我要问的一个真正的问题。
我在使用 Kotlin 编写的 Android 库处理 R8/混淆时遇到问题。
我有一个带有注释的公共 API 方法,@JvmStatic
该方法采用Lambda
as 参数。
例如,看看下面的代码,
typealias MyLambdaCallback = (String, Map<String, Any>) -> Unit
@Keep
object MyApi {
private var callback: MyLambdaCallback? = null
@JvmStatic
fun setCallback(callback: MyLambdaCallback) {
this.callback = callback
}
}
我已经添加@Jvmstatic
,以便Java
调用代码可以静态调用该方法,而不是做MyApi.INSTANCE.setCallback()
当我在没有 的情况下发布库时minification
,一切都很好,并且从两者调用代码Java
并且Kotlin
按预期编写。
但现在我想在打开时释放库minification
。
这就产生了一个问题。
这是错误
java.lang.IncompatibleClassChangeError:方法 'void setCallback(kotlin.jvm.functions.Function2)' 应该是 virtual 类型,但发现是 static 类型('com.demo.basic.Application' 的声明出现在/data/app/com.demo.basic-_0uJXPbtfs3UZ2Rp2h-RdQ==/base.apk!classes2.dex)
我是在某处犯了错误,还是预期这是某种限制?
我尝试了什么?
删除
@Jvmstatic
解决了这个问题,但它创建了丑陋的 Java 调用代码保留
@Jvmstatic
但删除Lambda
了将 Lambda 转换为 aninterface with one method
并且一切正常。不幸SAM for Kotlin classes
的是还没有,所以调用Kotlin
代码看起来很难看。
解决方案
这在 R8 问题跟踪器http://issuetracker.google.com/158393309上进行了跟踪,其中包含更多详细信息。
简而言之,这已在 R8 版本 2.1.35 中得到修复,可以通过对顶级build.gradle
文件进行以下更改来使用它:
repositories {
maven {
url 'https://storage.googleapis.com/r8-releases/raw'
}
}
dependencies {
classpath 'com.android.tools:r8:2.1.35' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}