在 Java class 中调用 Kotlin 挂起函数
Call Kotlin suspend function in Java class
假设我们有以下挂起函数:
suspend fun doSomething(): List<MyClass> { ... }
如果我想在我现有的 Java 类 之一(我现在无法转换为 Kotlin)中调用此函数并获取其 return 值我必须提供一个 Continuation<? super List<MyClass>>
作为它的参数(显然)。
我的问题是,我怎样才能实现一个。特别是它的 getContext
getter.
首先,将 org.jetbrains.kotlinx:kotlinx-coroutines-jdk8
模块添加到您的依赖项中。在您的 Kotlin 文件中,定义以下对应于 Java 异步 API 编写风格的异步函数:
fun doSomethingAsync(): CompletableFuture<List<MyClass>> =
GlobalScope.future { doSomething() }
现在使用 Java 中的 doSomethingAsync
就像您在 Java 世界中使用其他异步 API 一样。
对于协程 1.3.0 使用这个:
BuildersKt.launch(GlobalScope.INSTANCE,
Dispatchers.getMain(),//context to be ran on
CoroutineStart.DEFAULT,
(coroutineScope, continuation) -> suspendFunction(arguments)
);
对于 java < 8:
BuildersKt.launch(
GlobalScope.INSTANCE,
Dispatchers.getMain(),//context to be ran on
CoroutineStart.DEFAULT,
new Function2<CoroutineScope, Continuation<? super Unit>, Unit/*or your return type here*/>() {
@Override
public Unit/*or your return type here*/ invoke(CoroutineScope coroutineScope, Continuation<? super Unit> continuation) {
//do what you want
return Unit.INSTANCE; //or something with the defined type
}
}
);
我的 gradle 文件:
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0"
Kotlin对扩展函数使用静态类,launch是一个扩展函数,所以定义在BuildersKt中。第一个参数是扩展函数的目标,其余是扩展函数的参数。
如果你不想用org.jetbrains.kotlinx:kotlinx-coroutines-jdk8
,我有个新主意
在您的 kotlin 项目中编写以下代码。
@JvmOverloads
fun <R> getContinuation(onFinished: BiConsumer<R?, Throwable?>, dispatcher: CoroutineDispatcher = Dispatchers.Default): Continuation<R> {
return object : Continuation<R> {
override val context: CoroutineContext
get() = dispatcher
override fun resumeWith(result: Result<R>) {
onFinished.accept(result.getOrNull(), result.exceptionOrNull())
}
}
}
我写在我的Coroutines
class
然后你可以这样调用你的挂起函数:
Coroutines coroutines = new Coroutines();
UserUtils.INSTANCE.login("user", "pass", coroutines.getContinuation(
(tokenResult, throwable) -> {
System.out.println("Coroutines finished");
System.out.println("Result: " + tokenResult);
System.out.println("Exception: " + throwable);
}
));
login() 函数是一个挂起函数。
suspend fun login(username: String, password: String): TokenResult
对于您的代码,您可以:
doSomething(getContinuation((result, throwable) -> {
//TODO
}));
此外,你可能想运行你的回调代码在不同的线程(例如主线程),只需使用launch(Dispathers.Main)
包裹resumeWith()
假设我们有以下挂起函数:
suspend fun doSomething(): List<MyClass> { ... }
如果我想在我现有的 Java 类 之一(我现在无法转换为 Kotlin)中调用此函数并获取其 return 值我必须提供一个 Continuation<? super List<MyClass>>
作为它的参数(显然)。
我的问题是,我怎样才能实现一个。特别是它的 getContext
getter.
首先,将 org.jetbrains.kotlinx:kotlinx-coroutines-jdk8
模块添加到您的依赖项中。在您的 Kotlin 文件中,定义以下对应于 Java 异步 API 编写风格的异步函数:
fun doSomethingAsync(): CompletableFuture<List<MyClass>> =
GlobalScope.future { doSomething() }
现在使用 Java 中的 doSomethingAsync
就像您在 Java 世界中使用其他异步 API 一样。
对于协程 1.3.0 使用这个:
BuildersKt.launch(GlobalScope.INSTANCE,
Dispatchers.getMain(),//context to be ran on
CoroutineStart.DEFAULT,
(coroutineScope, continuation) -> suspendFunction(arguments)
);
对于 java < 8:
BuildersKt.launch(
GlobalScope.INSTANCE,
Dispatchers.getMain(),//context to be ran on
CoroutineStart.DEFAULT,
new Function2<CoroutineScope, Continuation<? super Unit>, Unit/*or your return type here*/>() {
@Override
public Unit/*or your return type here*/ invoke(CoroutineScope coroutineScope, Continuation<? super Unit> continuation) {
//do what you want
return Unit.INSTANCE; //or something with the defined type
}
}
);
我的 gradle 文件:
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0"
Kotlin对扩展函数使用静态类,launch是一个扩展函数,所以定义在BuildersKt中。第一个参数是扩展函数的目标,其余是扩展函数的参数。
如果你不想用org.jetbrains.kotlinx:kotlinx-coroutines-jdk8
,我有个新主意
在您的 kotlin 项目中编写以下代码。
@JvmOverloads
fun <R> getContinuation(onFinished: BiConsumer<R?, Throwable?>, dispatcher: CoroutineDispatcher = Dispatchers.Default): Continuation<R> {
return object : Continuation<R> {
override val context: CoroutineContext
get() = dispatcher
override fun resumeWith(result: Result<R>) {
onFinished.accept(result.getOrNull(), result.exceptionOrNull())
}
}
}
我写在我的Coroutines
class
然后你可以这样调用你的挂起函数:
Coroutines coroutines = new Coroutines();
UserUtils.INSTANCE.login("user", "pass", coroutines.getContinuation(
(tokenResult, throwable) -> {
System.out.println("Coroutines finished");
System.out.println("Result: " + tokenResult);
System.out.println("Exception: " + throwable);
}
));
login() 函数是一个挂起函数。
suspend fun login(username: String, password: String): TokenResult
对于您的代码,您可以:
doSomething(getContinuation((result, throwable) -> {
//TODO
}));
此外,你可能想运行你的回调代码在不同的线程(例如主线程),只需使用launch(Dispathers.Main)
包裹resumeWith()