android - R8 去除反射所需的 Kotlin 伴生对象

标签 android kotlin reflection proguard android-r8

我有一个带有实现工厂接口(interface)的伴随对象的类。

class GoalInspectorData(
    ...
) {

    companion object : DataClassFactory<GoalInspectorData> {

        override fun fromV8Object(v8Object: V8Object): GoalInspectorData {
            ...
        }
    }
}

我有一些代码在运行时使用反射检查此类,以查看该类是否提供工厂方法。它通过检查该类是否具有伴随对象( companionObjectInstance )以及如果有,则该伴随对象是否实现工厂接口(interface)来实现这一点。

internal inline fun <reified T> convert(obj: Any): T {

    val companionObject = T::class.companionObjectInstance

    @Suppress("UNCHECKED_CAST")
    return when {
        T::class in builtInClasses -> obj as T
        companionObject as? DataClassFactory<T> != null -> companionObject.fromV8Object(obj as V8Object)
        else -> throw IllegalArgumentException("No converter for type ${T::class}")
    }
}

这一切在调试版本中都可以正常工作。

它在启用 R8 的发布版本中失败( build.gradle 中的 minifyEnabled true )。它失败了,因为 companionObjectInstance返回 null .

我正在使用不优化 Proguard 配置:

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

在我自己的 proguard-rules.pro 我几乎添加了每个 -keep我可以想象的规则试图保留这个伴随对象,并添加了@Keep注释一切,但没有任何作用。 R8决心将其剥离。

例如:
-keep class my.package.** {
    *;
}
-keep interface my.package.** {
    *;
}

-if class **$Companion extends **
-keep class <2>
-if class **$Companion implements **
-keep class <2>

有没有其他的-keep指示 R8 保留此伴随对象的规则或配置选项?

最佳答案

首先,保持规则

-keep class my.package.** {
    *;
}

应该足以保留所有类 - 包括程序中的伴随类。您应该不需要 -dontoptimize标志,所以使用配置proguard-android-optimize.txt应该没事。

但是,当您使用 Kotlin 反射时,您可能还需要保留注释类 kotlin.Metadata和具有以下规则的运行时可见注释:
-keep @interface kotlin.Metadata {
  *;
}
-keepattributes RuntimeVisibleAnnotations

如果这仍然不起作用,请提交 R8 issue ?如果您可以包含一个简单的复制,那就太好了。

关于android - R8 去除反射所需的 Kotlin 伴生对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57974556/

相关文章:

kotlin - 惯用箭

android - Kotlin/Firebase/Android Studio-java.util.NoSuchElementException : List is empty

c# - 序列化 DataAnnotations

android - Android Studio Canary 中的 Kotlin Android 扩展错误

android - 有没有办法以编程方式在 Android 中读取/访问电子邮件或收件箱?

kotlin - 在 Kotlin 中实现域 <-> dto 映射器功能

reflection - 区分同一包中具有相同名称的结构

c# - 当 T 为 IEnumerable<TP> 时,将类型 T 的泛型参数转换为 List<TP>

java - 如何在 GridView 中交换图像 (Android)

java - 使用 GSON 和 Retrofit 时反序列化内部类