7

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

class GoalInspectorData(
    ...
) {

    companion object : DataClassFactory<GoalInspectorData> {

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

我有一些代码在运行时使用反射检查此类,以查看该类是否提供工厂方法。它通过检查该类是否具有伴随对象companionObjectInstance

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 的发布版本中失败(minifyEnabled truebuild.gradle中)。它失败了,因为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 保留此伴随对象?

4

1 回答 1

7

首先,保持规则

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

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

但是,当您使用 Kotlin 反射时,您可能还需要kotlin.Metadata使用以下规则保持注解类和运行时可见注解:

-keep @interface kotlin.Metadata {
  *;
}
-keepattributes RuntimeVisibleAnnotations

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

于 2019-09-17T15:51:21.110 回答