简体   繁体   English

返回值(Int) from Kotlin coroutine from Java call

[英]Returning value (Int) from Kotlin coroutine from Java call

I've been struggling to return a value from a Kotlin coroutine back to Java for what feels like way too long.我一直在努力将值从 Kotlin 协程返回到 Java,感觉时间太长了。 This is how I finally got it to work, but am not 100% sure that it is the best way.这就是我最终让它工作的方式,但我不是 100% 确定这是最好的方式。 The ways I get a return value when returning to Kotlin are not working.返回 Kotlin 时获取返回值的方法不起作用。 I'm simply updating the UI with the total row count in the SQLite db.我只是用 SQLite 数据库中的总行数更新 UI。

Here's my call from Java (activity) from main thread这是我从主线程 Java(活动)打来的电话

tv.setText(String.valueOf(DbUtil.getDbRowCount()));

And here's the method in DbUtil (Kotlin object Class)这是 DbUtil 中的方法(Kotlin object 类)

@JvmStatic
fun getDbRowCount(): Int = runBlocking {
    withContext(IO){DbHelper.getInstance().dbRowCount}
}

My questions:我的问题:

  1. Does adding the withContext(IO) keep the main thread from being blocked?添加 withContext(IO) 是否可以防止主线程被阻塞?
  2. If this does in fact block, how can I rewrite this so that it doesn't.如果这确实阻塞了,我该如何重写它以使其不阻塞。

Using runBlocking does what it says, blocks for the result.使用 runBlocking 会按照它说的去做,阻塞结果。 So dispatching to the IO dispatcher has no effect.所以调度到 IO 调度器没有效果。

A suspending function can only be callable by a coroutine, so you must be inside a coroutine in order to call any suspendable function.挂起的 function 只能由协程调用,因此您必须在协程内才能调用任何可挂起的 function。

  1. First to remove the barrier, ie to make the function callable from non-coroutine body:首先移除障碍,即使 function 可从非协程主体调用:
@JvmStatic
val scope = CoroutineScope(EmptyCoroutineContext)

@JvmStatic
fun getDbRowCount(): Deferred<Int> = scope.async(Dispatchers.IO) {
    DbHelper.getInstance().dbRowCount
}

If you are on a coroutine (in Kotlin code) you can simply call .await() to get Int result (suspending).如果您在协程中(在 Kotlin 代码中),您可以简单地调用.await()来获取 Int 结果(挂起)。

  1. To make the result interoperable with Java, you can convert the Deferred from the coroutine to a CompletableFuture.要使结果与 Java 互操作,您可以将 Deferred 从协程转换为 CompletableFuture。
// requires: latest $version as of now is 1.3.9
// implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$version"
CompletableFuture cf = FutureKt.asCompletableFuture(getDbRowCount());
  1. Then you can use the callback-style to listen to the result:然后你可以使用回调风格来收听结果:
cf.whenCompleteAsync((result, exception) -> {
    // Ensure UI change happens on Main/UI thread.
    new Handler(context.getMainLooper()).post(() -> tv.setText(String.valueOf(result)));
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM