在Java类中调用Kotlin暂停函数

时间:2018-10-18 08:12:15

标签: java kotlin kotlin-coroutines

假设我们具有以下暂停功能:

suspend fun doSomething(): List<MyClass> { ... }

如果我想在我现有的Java类之一中调用此函数(暂时无法将其转换为Kotlin)并获取其返回值,则必须提供Continuation<? super List<MyClass>>作为其参数(明显)。

我的问题是,我该如何实施。特别是它的getContext吸气剂。

3 个答案:

答案 0 :(得分:14)

首先,将org.jetbrains.kotlinx:kotlinx-coroutines-jdk8模块添加到您的依赖项中。在您的Kotlin文件中,定义以下与Java编写异步API样式相对应的异步函数:

fun doSomethingAsync(): CompletableFuture<List<MyClass>> =
    GlobalScope.future { doSomething() }

现在,以与使用Java世界中其他异步API相同的方式使用Java中的doSomethingAsync

答案 1 :(得分:3)

如果您不想使用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类中写它

然后您可以像下面这样调用您的暂停函数:

            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
}));

答案 2 :(得分:2)

对于协程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中定义。第一个参数是扩展功能的目标,其余参数是扩展功能的参数。