Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call Kotlin suspend function in Java class

Assume we have the following suspend function:

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

If I want to call this function in one of my existing Java classes (which I'm not able to convert to Kotlin for now) and get its return value I have to provide a Continuation<? super List<MyClass>> as its parameter (Obviously).

My question is, How can I implement one. Specially its getContext getter.

like image 347
mrtaikandi Avatar asked Oct 18 '18 08:10

mrtaikandi


People also ask

Can we call suspend function from Java?

Java Thread suspend() methodThe suspend() method of thread class puts the thread from running to waiting state. This method is used if you want to stop the thread execution and start it again when a certain event occurs. This method allows a thread to temporarily cease execution.

Can I call Kotlin method in Java?

Kotlin has been designed from the beginning to fully interoperate with Java, and both JetBrains and Google have pushed in that direction. For instance, IntelliJ and Android Studio allow users to convert files from Java to Kotlin. The conversion is not always problem-free, but it generally does a good job.

How does Kotlin handle suspend function?

We just have to use the suspend keyword. Note: Suspend functions are only allowed to be called from a coroutine or another suspend function. You can see that the async function which includes the keyword suspend. So, in order to use that, we need to make our function suspend too.

Can we use coroutines in Java?

You can implement "coroutines" as threads/thread pools behind the scenes. You can do tricksy things with JVM bytecode behind the scenes to make coroutines possible. The so-called "Da Vinci Machine" JVM implementation has primitives that make coroutines doable without bytecode manipulation.


2 Answers

First, add org.jetbrains.kotlinx:kotlinx-coroutines-jdk8 module to your dependencies. In your Kotlin file define the following async function that corresponds to Java style of writing async APIs:

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

Now use doSomethingAsync from Java in the same way as you are using other asynchronous APIs in the Java world.

like image 194
Roman Elizarov Avatar answered Oct 18 '22 22:10

Roman Elizarov


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 write it in my Coroutines class

Then you can call your suspend function like:

            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() function is a suspend function.
suspend fun login(username: String, password: String): TokenResult

For your code, you can:

doSomething(getContinuation((result, throwable) -> {         //TODO })); 
like image 35
Kenvix Zure Avatar answered Oct 18 '22 20:10

Kenvix Zure