Существует блок сопрограммы, который может запускать функции приостановки.
Но я вызываю функцию путем invoke
через отражение. Это вызов Java-стиля, по-видимому, простой вызов не будет работать. Существуют ли способы запуска отраженного метода асинхронно? Как дождаться этого метода?
import kotlin.coroutines.experimental.* class TestClass(val InString: String) { suspend fun printString() { println(InString) } } fun launch(context: CoroutineContext, block: suspend () -> Unit) = block.startCoroutine(StandaloneCoroutine(context)) private class StandaloneCoroutine(override val context: CoroutineContext): Continuation<Unit> { override fun resume(value: Unit) {} override fun resumeWithException(exception: Throwable) { val currentThread = Thread.currentThread() currentThread.uncaughtExceptionHandler.uncaughtException(currentThread, exception) } } fun main(args: Array<String>) { launch(EmptyCoroutineContext) { val a = TestClass("TestString"); for (method in a.javaClass.methods) { if (method.name == "printString") method.invoke(a) // Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments } } }
Каждый метод suspend
в Котлине представлен на JVM с помощью преобразования CPS, который поясняется в сопроводительном документе coroutines . Отражение Java не знает об этом, и отражение Котлина в настоящее время не предоставляет удобные средства для выполнения вызова функции приостановки.
Вам придется делать вызов с помощью преобразования CSP самостоятельно через вспомогательную функцию. Я предлагаю реализовать для этой цели следующий помощник:
import java.lang.reflect.Method import kotlin.coroutines.experimental.intrinsics.* suspend fun Method.invokeSuspend(obj: Any, vararg args: Any?): Any? = suspendCoroutineOrReturn { cont -> invoke(obj, *args, cont) }
Теперь, если вы замените invoke
на invokeSuspend
в своем коде, тогда он будет работать так же, как и ожидалось.