如何从 Java 7 调用 Kotlin 挂起协程函数

我试图从Java 7调用Kotlin函数。我正在使用协程,这个调用的函数正在挂起,例如:

suspend fun suspendingFunction(): Boolean {
    return async { longRunningFunction() }.await()
}

suspend fun longRunningFunction() : Boolean {
    delay(400)
    return true
}

我在版本0.25.3中使用协程,我可以通过将实例作为暂停函数的参数来模拟简单的Java回调风格,例如Continuation<U>

CoroutinesKt.suspendingFunction(new Continuation<Boolean>() {
    @Override
    public CoroutineContext getContext() {
        return EmptyCoroutineContext.INSTANCE;
    }

    @Override
    public void resume(Boolean value) {
        doSomethingWithResult(value);
    }

    @Override
    public void resumeWithException(@NotNull Throwable throwable) {
        handleException(throwable);
    }
});

但是,在更新到完全稳定的1.0.1版本后,我认为这不再可能。假设挂起函数的更新版本如下所示:

suspend fun suspendingFunction(): Boolean {
    return GlobalScope.async { longRunningFunction() }.await()
}

Continuation<U>现在使用类,它似乎无法从Java中使用(这是有道理的,因为它是内联类)。我试图使用一些来自协程的子类,但它们都是内部的或私有的。ResultContinuation

我知道通常建议将协程转换为CompletableFuture,但我使用的是Android,这意味着只有Java 7。另一方面,简单太愚蠢了,因为我不想定期检查函数是否完成 - 我只想在完成后被调用。我真的很想避免添加新的库或许多其他类/方法。Future

有没有简单的方法直接从Java 7调用挂起函数?

由于Kotlin试图与Java非常可互操作,我想会有一些简单的方法来做到这一点,但我还没有找到它。


答案 1

根据您的环境,您有几种选择。

  1. 如果在项目中使用,则该模块具有实用程序函数,用于在协程和 Rx 数据类型之间来回转换。RxJava2kotlinx-coroutines-rx2

suspend fun sayHello(): String {
    delay(1000)
    return "Hi there"
}

fun sayHelloSingle(): Single<String> = GlobalScope.rxSingle { sayHello() }
  1. 否则,您可以添加一个与旧类的定义匹配的新类,并且在 Java 端也很有用。Continuation

示例(Kotlin 端)

abstract class Continuation<in T> : kotlin.coroutines.Continuation<T> {
    abstract fun resume(value: T)
    abstract fun resumeWithException(exception: Throwable)
    override fun resumeWith(result: Result<T>) = result.fold(::resume, ::resumeWithException)
}   

示例(Java 端)

sayHello(new Continuation<String>() {
    @Override
    public CoroutineContext getContext() {
        return EmptyCoroutineContext.INSTANCE;
    }

    @Override
    public void resume(String value) {
        doSomethingWithResult(value);
    }

    @Override
    public void resumeWithException(@NotNull Throwable throwable) {
        doSomethingWithError(throwable);
    }
});

答案 2

您可以使用 BuildersKt。这已经包含在implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0"

    BuildersKt.launch(
            GlobalScope.INSTANCE,
            (CoroutineContext) Dispatchers.getMain(),
            CoroutineStart.DEFAULT,
            (Function2<CoroutineScope, Continuation<? super Unit>, Unit>) (coroutineScope, continuation) -> {
                // your code here
                return Unit.INSTANCE;
            }
    );

推荐