If you dont want to use org.jetbrains.kotlinx:kotlinx-coroutines-jdk8, I have a new idea.
Write below code in your kotlin project.
@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()) } } }
I wrote it in my Coroutines class
Then you can call your suspend function like:
Coroutines coroutines = new Coroutines(); // My coroutines utils class 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() function is a suspend function.
suspend fun login(username: String, password: String): TokenResult
For your code, you can:
doSomething(getContinuation((result, throwable) -> { //TODO }));
Besides, you may want to run your callback code in a different thread (e.g. Main thread), just use launch(Dispathers.Main) to wrap resumeWith()
... override fun resumeWith(result: Result<R>) { launch(Dispathers.Main) { onFinished.accept(result.getOrNull(), result.exceptionOrNull()) } } ...
Update: My friend has developed a plugin kotlin-jvm-blocking-bridge that can automatically generate blocking bridges for calling suspend functions from Java with minimal effort, also give it a try.
Continuationand call asuspend fun, but in Kotlin 1.3ContinuationdeclaresresumeWith(Result), whereResultis a discriminated union of the result and aninternal class Failureand there's just no way to supply that from Java, save for using reflection to access private members in Kotlin implementation.