Kotlin、Proguard 和 lambdas

Posted

技术标签:

【中文标题】Kotlin、Proguard 和 lambdas【英文标题】:Kotlin, Proguard and lambdas 【发布时间】:2016-05-31 23:29:54 【问题描述】:

我有一个简洁的函数可以在视图上做一些事情:

fun<T : View> Activity.withView(nr : Int, fn : T.()->Unit) 
    (findViewById(nr) as T?)?.fn()

现在,当我在我的活动中使用此功能时:

    withView<Spinner>(R.id.spinner_toolbar) 
        adapter = AdapterIndeksuDlaSpinnera(this@NewMainActivity, PlaylistIndex)

...在我使用 ProGuard 之前一切正常。我可以看到AdapterIndeksuDlaSpinnera 像预期的那样被损坏了,但是当使用“无法加载类 AdapterIndeksuDlaSpinnera”进行保护时应用程序失败(虽然它应该抱怨损坏的适配器名称)。

我能够通过禁用可在我的withView 中使用的所有适配器来创建临时解决方法

-keep class pl.qus.xenoamp.adapter.**  *; 

但我觉得这不是一个好的解决方案(而且我不知道其他类会以这种方式失败!)。那么任何人都可以解释问题是什么以及我应该添加什么 ProGuard 行来潜在地修复 withView 中使用的其他类的类似情况?

【问题讨论】:

能否请您发布适配器的.class 文件以及包含闭包的文件?它们可以在 android 项目的build/intermediates/classes/ 中找到。 让我们continue this discussion in chat。 【参考方案1】:

这是一个艰难的过程。简而言之,Proguard 并不了解 Kotlin。它使用简单的代码分析来检测Class.forName() 之类的东西并解决它们,但对于更复杂的东西可能会失败。您需要查看从build 子目录生成的.class 文件(您可以发布相关文件吗?)以了解实际情况。

现在你可以做两件事:

要求 Kotlin 开发人员为 Kotlin 编译器添加适当的混淆/优化支持:这确实是正确的方法,现有的每个非 Java 编译器都证明了这一点; 从混淆中排除您自己的来源(大多数活动和视图无论如何都不会被很好地混淆)。

【讨论】:

您可以在youtrack.jetbrains.com 处添加诸如混淆之类的功能请求...确保包括编译后混淆器在仅给定类文件时知道什么是安全的或不安全的困难。 (但话又说回来,如果不知道当前编译模块之外的用途也很难混淆,因此编译时版本也可能有问题,只是不同的问题)

以上是关于Kotlin、Proguard 和 lambdas的主要内容,如果未能解决你的问题,请参考以下文章

添加 kotlin 协程和房间后无法进行发布构建,proguard 警告

带有 proguard 的 Kotlin AAR 库:如何只保留类和方法名?

带有 Proguard 的 Kotlin 反射失败

启用 Proguard 时未找到 kotlin.Any

如何使用 proguard 定位 kotlin `internal` 类?

Kotlin 反映 proguard SmallSortedMap