【问题标题】:Why is Kotlin function name being mangled when passing Duration为什么在传递 Duration 时 Kotlin 函数名称会被破坏
【发布时间】:2021-05-14 11:54:28
【问题描述】:

在我当前的 Android 应用程序中,我正在研究 Duration 与协程延迟功能的使用,如下所示:-

class WorkerTwo(private val context: Context, private val params: WorkerParameters) : CoroutineWorker(context, params) {

    @ExperimentalTime
    override suspend fun doWork(): Result = coroutineScope {
        (0..100 step 30).forEach {
            setProgress(workDataOf(PROGRESS to it))

            delay(Duration.Companion.seconds(1L)) // CRASH HERE!!!!!!!!!!!!
        }

        Result.success()
    }
}

但是,当我安装并运行我的应用程序时,它会崩溃,如下所示

 Caused by: java.lang.NoSuchMethodError: No static method delay-p9JZ4hM(JLkotlin/coroutines/Continuation;)Ljava/lang/Object; in class Lkotlinx/coroutines/DelayKt; or its super classes (declaration of 'kotlinx.coroutines.DelayKt' appears in /data/app/org.research.development.versiononefive-nC90emPcnKpqBIJrwhWkgQ==/base.apk)
        at org.research.development.versiononefive.WorkerTwo$doWork$2.invokeSuspend(WorkerTwo.kt:19)
 

delay 方法名称被修改为 delay-p9JZ4hM,为什么会出现这种情况?

更新

我通过将其添加到我的 gradle 文件来解决此问题

implementation "androidx.work:work-runtime:2.7.0-alpha03"
implementation "androidx.work:work-runtime-ktx:2.7.0-alpha03"

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0-RC"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0-RC"

并像这样重构延迟函数调用:-

delay(Duration.seconds(1L)) // CRASH HERE!!!!!!!!!!!!

【问题讨论】:

  • 由于 Duration 的后备字段类型(从 Double 到 Long)的底层变化,协程中损坏的 delay(Duration) 方法在 Kotlin 1.4.x 和 Kotlin 1.5 之间发生了变化。为此,您需要使用 Kotlin 1.5.0 和协同程序 >= 1.5.0-RC 进行编译,或者使用以前版本的协同程序和 Kotlin 1.4.x。

标签: kotlin


【解决方案1】:

Duration 是一个内联类(Kotlin 1.5+ 中的值类)。

这意味着在 JVM 中根本没有 Duration 类。它由没有包装器的Double(1.5+ 中的Long)表示。

当您编写一个将内联类作为参数的方法时,Kotlin 会修改名称,使其与采用底层值的重载具有不同的签名,即,这样您就可以同时拥有 @987654325 @ 和 delay(Double) 即使在 JVM 中参数类型相同。

关于你的错误:

如前所述,在 Kotlin 1.5 中内联类更改为值类,并且还有一个新功能允许显式设置方法的 JVM 名称。

您的错误的可能原因是您正在编译 Kotlin 1.5 并使用旧版本的库运行,反之亦然,并且 delay 的重命名名称与另一个不同。此外,Duration 的底层类型已更改,因此即使名称匹配,您也无法调用该方法。

【讨论】:

    【解决方案2】:

    我没有看到 Duration.Companion.seconds 方法,可能是因为我有另一个 Kotlin 版本。 但是您可以像这里一样使用持续时间:

    delay(1.seconds)
    

    另外,你可以使用时间毫秒:

    delay(1000L)
    

    【讨论】:

    • 谢谢我没有发现完整的代码已经添加了 Companion。
    • 仅供参考,Int.seconds 扩展已在 Kotlin 1.5 中弃用,并添加了相应的伴随对象工厂方法 (Duration.seconds(1))。
    猜你喜欢
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 2016-09-04
    • 2023-01-19
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 2015-02-06
    相关资源
    最近更新 更多