在用 Kotlin 编写的 Android 库的公共 API 中处理 R8 + JvmStatic Annotation + Lambda
Posted
技术标签:
【中文标题】在用 Kotlin 编写的 Android 库的公共 API 中处理 R8 + JvmStatic Annotation + Lambda【英文标题】:Dealing with R8 + JvmStatic Annotation + Lambda in public API for Android Library written in Kotlin 【发布时间】:2020-09-26 16:30:01 【问题描述】:首先,请注意我并不期待why do you want to obfuscate library
cmets。这是我要问的一个真正的问题。
我在使用 Kotlin 编写的 android 库处理 R8/混淆时遇到问题。
我有一个用 @JvmStatic
注释的公共 API 方法,该方法采用 Lambda
作为参数。
例如,看看下面的代码,
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.应用程序'出现在 /data/app/com.demo.basic-_0uJXPbtfs3UZ2Rp2h-RdQ==/base.apk!classes2.dex)
我是否在某处犯了错误,或者这是某种限制?
我做了什么?
删除 @Jvmstatic
解决了这个问题,但它创建了丑陋的 Java 调用代码
保留@Jvmstatic
,但删除Lambda
,将Lambda 转换为interface with one method
,一切正常。不幸的是SAM for Kotlin classes
还没有,所以调用Kotlin
代码看起来很丑。
【问题讨论】:
你使用的是什么版本的 Kotlin 编译器? @RyanM1.3.72
@RyanM 我发现问题出在@Jvmstatic
附近。我更新了Q的内容。看看你是否可以帮忙。
这是一个包含很多细节的好问题。对我来说,这确实看起来像是某处工具中的错误(即,不是您的错误)-我目前没有时间深入研究它,但是如果可以的话,我会看一下找点时间。
好的。没问题。谢谢@RyanM
【参考方案1】:
这在 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.
【讨论】:
【参考方案2】:R8 团队在 R8 版本中有 fixed 这个问题以及相关问题 b/158400283 2.1.42
修复应该已经在Android Studio 4.1 beta
或更高版本中可用,但如果您使用的是稳定版Android Studio 4.0
,则将以下内容添加到您的*** build.gradle 文件中:
buildscript
repositories
maven
url 'https://storage.googleapis.com/r8-releases/raw'
dependencies
classpath 'com.android.tools:r8:2.1.42' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
【讨论】:
以上是关于在用 Kotlin 编写的 Android 库的公共 API 中处理 R8 + JvmStatic Annotation + Lambda的主要内容,如果未能解决你的问题,请参考以下文章
用 Kotlin 编写的 Android 库,提供对 Java 应用程序的支持
如何在用 Kotlin 编写的 JUnit 5 测试类中注入 Spring bean?
将 Kotlin 运行时库添加到 android 中的 aar
在 Kotlin 中编写具有特征的 Android 测试时出现 java.lang.VerifyError