Как вызвать функцию приостановки сопрограммы Kotlin из Java 7 - PullRequest
0 голосов
/ 03 января 2019

Я пытаюсь вызвать функцию Kotlin из Java 7. Я использую сопрограммы, и эта вызываемая функция приостанавливается, например:

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> теперь использует класс Result, который кажется непригодным для Java (что имеет смысл, поскольку он встроенный класс). Я пытался использовать некоторый подкласс Continuation из сопрограмм, но они все внутренние или частные.

Я знаю, что обычно рекомендуется преобразовать сопрограмму в CompletableFuture, но я работаю на Android, что означает только Java 7. Простой Future, с другой стороны, слишком тупой, так как я не хочу периодически проверять, завершена ли функция - я просто хочу, чтобы ее вызывали, когда она закончена. И я действительно хотел бы избежать добавления новых библиотек или множества дополнительных классов / методов.

Есть ли простой способ вызвать функцию приостановки прямо из Java 7?

Поскольку Kotlin пытается очень легко взаимодействовать с Java, я думаю, что есть какой-то простой способ сделать это, но я еще не нашел его.

1 Ответ

0 голосов
/ 04 января 2019

У вас есть несколько вариантов в зависимости от вашей среды.

  1. Если вы используете RxJava2 в проекте, модуль kotlinx-coroutines-rx2 имеет служебные функции для преобразования назад и вперед между сопрограммами и типами данных Rx.

Пример

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

fun sayHelloSingle(): Single<String> = GlobalScope.rxSingle { sayHello() }
  1. В противном случае вы можете добавить новый класс Continuation, который соответствует определению старого и также полезен на стороне Java.

Пример (сторона Котлина)

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);
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...