如何从 Java 7 调用 Kotlin 挂起协程函数
How to call Kotlin suspending coroutine function from Java 7
我正在尝试从 Java 7 调用 Kotlin 函数。我正在使用协同程序,这个被调用的函数正在挂起,例如:
suspend fun suspendingFunction(): Boolean {
return async { longRunningFunction() }.await()
}
suspend fun longRunningFunction() : Boolean {
delay(400)
return true
}
我在 0.25.3 版中使用协程,我可以通过将 Continuation<U>
实例作为参数传递给挂起函数来模拟简单的 Java 回调样式,例如
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>
现在使用 Result
class,这似乎无法从 Java 中使用(这很有意义,因为它是内联的 class)。我试图从协程中使用 Continuation
的一些子 class,但它们都是内部的或私有的。
我知道通常是,但我在Android,这意味着只有Java 7。另一方面,简单 Future
太笨了,因为我不想定期检查功能是否完成 - 我只想在完成时被调用。我真的很想避免添加新的库或许多额外的 classes/methods。
有什么简单的方法可以直接从Java7调用挂起函数吗?
由于 Kotlin 试图与 Java 实现高度互操作,我想会有一些简单的方法可以做到这一点,但我还没有找到它。
根据您的环境,您有多种选择。
- 如果您在项目中使用
RxJava2
,模块 kotlinx-coroutines-rx2
具有在协程和 Rx 数据类型之间来回转换的实用函数。
例子
suspend fun sayHello(): String {
delay(1000)
return "Hi there"
}
fun sayHelloSingle(): Single<String> = GlobalScope.rxSingle { sayHello() }
- 否则,您可以添加一个新的
Continuation
class 来匹配旧的定义并且在 Java 方面也很有用。
示例(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);
}
});
您可以使用 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;
}
);
我正在尝试从 Java 7 调用 Kotlin 函数。我正在使用协同程序,这个被调用的函数正在挂起,例如:
suspend fun suspendingFunction(): Boolean {
return async { longRunningFunction() }.await()
}
suspend fun longRunningFunction() : Boolean {
delay(400)
return true
}
我在 0.25.3 版中使用协程,我可以通过将 Continuation<U>
实例作为参数传递给挂起函数来模拟简单的 Java 回调样式,例如
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>
现在使用 Result
class,这似乎无法从 Java 中使用(这很有意义,因为它是内联的 class)。我试图从协程中使用 Continuation
的一些子 class,但它们都是内部的或私有的。
我知道通常是Future
太笨了,因为我不想定期检查功能是否完成 - 我只想在完成时被调用。我真的很想避免添加新的库或许多额外的 classes/methods。
有什么简单的方法可以直接从Java7调用挂起函数吗?
由于 Kotlin 试图与 Java 实现高度互操作,我想会有一些简单的方法可以做到这一点,但我还没有找到它。
根据您的环境,您有多种选择。
- 如果您在项目中使用
RxJava2
,模块kotlinx-coroutines-rx2
具有在协程和 Rx 数据类型之间来回转换的实用函数。
例子
suspend fun sayHello(): String {
delay(1000)
return "Hi there"
}
fun sayHelloSingle(): Single<String> = GlobalScope.rxSingle { sayHello() }
- 否则,您可以添加一个新的
Continuation
class 来匹配旧的定义并且在 Java 方面也很有用。
示例(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);
}
});
您可以使用 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;
}
);