J'ai une API que je ne contrôle pas .... qui contient une méthode qui fait un travail et renvoie les résultats de manière asynchrone. Je voudrais appeler cette méthode de manière synchrone dans certaines parties de ma demande. Je l' ai fait en ajoutant une classe ResultHandler
qui capte et renvoie le résultat. Y at - il une meilleure façon de le faire que la façon dont je l' ai fait ci - dessous? Peut-être en utilisant Kotlin standard (ou Java en dernier recours) Méthodes bibliothèque. Ma préférence serait pour awaitReply
retourner le résultat et aussi pour enlever le CountdownLatch
.
class Main {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val result1 = Main().nonAsyncMethod1(arrayListOf(1, 2, 3, 4, 5))
result1.elements.forEach { println(it) }
}
}
class Result1(var elements: Collection<String>)
fun asyncMethod1(x: Collection<Int>, callback: (Result1) -> Unit) {
Thread().run {
// do some calculation
Thread.sleep(1000)
callback(Result1(x.map { "\"$it\"" }.toList()))
}
}
private fun nonAsyncMethod1(entities: Collection<Int>): Result1 {
val resultHandler = ResultHandler<Result1>()
awaitReply<Result1> {
asyncMethod1(entities, resultHandler)
}
return resultHandler.getResponse()
}
open class ResultHandler<T : Any> : (T) -> Unit {
private lateinit var response: T
private val latch = CountDownLatch(1)
override fun invoke(response: T) {
latch.countDown()
this.response = response
}
fun getResponse(): T {
latch.await()
return response
}
}
private fun <T : Any> awaitReply(call: () -> Unit) {
return call.invoke()
}
}
Merci à la pointe de the_dani
Je viens à la GÉRÉ solution ci - dessous à l' aide coroutines comme indiqué dans « callbacks d'emballage section » du Kotlin Coroutines documentation:
class Main {
companion object {
@JvmStatic
fun main(args: Array<String>) = runBlocking {
val result1 = Main().nonAsyncMethod1(arrayListOf(1, 2, 3, 4, 5))
result1.elements.forEach { println(it) }
}
}
class Result1(var elements: Collection<String>)
fun asyncMethod1(x: Collection<Int>, callback: (Result1) -> Unit) {
Thread().run {
// do some calculation
Thread.sleep(1000)
callback(Result1(x.map { "\"$it\"" }.toList()))
}
}
suspend fun nonAsyncMethod1(entities: Collection<Int>): Result1 = suspendCoroutine {
cont ->
asyncMethod1(entities) { cont.resume(it) }
}
}