首页 > 解决方案 > 当回调是类的字段时,将回调转换为suspendCoroutine

问题描述

我想将一些基于回调的 3rd-party API 转换为易于使用的简单挂起函数。这是我的实现的简化示例。

class LibraryWrapper {

    private lateinit var onFooFired: (Boolean) -> Unit

    private val libraryCallback = object : LibraryCallback {
        override fun foo(result: Boolean) {
            onFooFired(result)
        }
    }
    private val library = Library(libraryCallback)

    suspend fun bar(): Boolean {
        return suspendCoroutine { performingBar: Continuation<Boolean> ->
            onFooFired = {fooResult -> performingBar.resume(fooResult) }
            library.bar()
        }
    }
}

但这种解决方案有时有效,有时无效。这个 lambda 字段存在这样的问题,有时它会正确初始化,但有时会抛出异常“lateinit property onFooFired is not initialized”

这很奇怪,因为我确实在运行 library.bar() 之前对其进行了初始化,并且仅在调用library.bar() 之后才调用 LibraryCallback 的 foo 。

标签: androidkotlincallbackkotlin-coroutineskotlin-lateinit

解决方案


首先,我认为当您不控制字段的初始化时,使用“lateinit var”不是一个好方法。仅当您有初始化的承诺时才使用 lateinit。

尝试使用可为空的字段实现,例如

private var onFooFired: ((Boolean) -> Unit)? = null

并在回调中:

private val libraryCallback = object : LibraryCallback {
        override fun foo(result: Boolean) {
            onFooFired?.invoke(result)
        }
    }

在这种情况下,除非您没有实现“onFooFired” lambda,否则它不会调用


推荐阅读