【问题标题】:Returning value (Int) from Kotlin coroutine from Java call从 Java 调用的 Kotlin 协程返回值 (Int)
【发布时间】:2020-10-10 15:19:04
【问题描述】:

我一直在努力将 Kotlin 协程中的值返回给 Java,这感觉太久了。这就是我最终让它工作的方式,但我不能 100% 确定这是最好的方法。 返回 Kotlin 时获得返回值的方式不起作用。我只是用 SQLite db 中的总行数更新 UI。

这是我从主线程的 Java(活动)调用

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

这是 DbUtil(Kotlin 对象类)中的方法

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

我的问题:

  1. 添加 withContext(IO) 是否可以防止主线程被阻塞?
  2. 如果这确实阻塞,我该如何重写它以使其不会阻塞。

【问题讨论】:

  • > 可以,但是这样可以吗?,它不会有任何将它分派到IO池的效果,它会阻塞调用线程,并且您似乎正在更改值一个 UI 元素,所以你很可能是从主线程调用它,所以它可能会带来不稳定的体验,因为主线程将被阻塞直到函数返回。
  • @AnimeshSahu 查看我的附加编辑

标签: java android kotlin kotlin-coroutines


【解决方案1】:

使用 runBlocking 执行它所说的,阻塞结果。所以分派给 IO 分派器是没有效果的。

挂起函数只能被协程调用,所以你必须在协程中才能调用任何可挂起函数。

  1. 首先移除障碍,即使函数可从非协程体调用:
@JvmStatic
val scope = CoroutineScope(EmptyCoroutineContext)

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

如果您使用的是协程(在 Kotlin 代码中),您可以简单地调用 .await() 来获取 Int 结果(暂停)。

  1. 要使结果与 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. 然后你可以使用回调样式来监听结果:
cf.whenCompleteAsync((result, exception) -> {
    // Ensure UI change happens on Main/UI thread.
    new Handler(context.getMainLooper()).post(() -> tv.setText(String.valueOf(result)));
});

【讨论】:

  • 无法解析符号“FutureKt”。我确实有最新的依赖项
  • @seekingStillness 捆绑在kotlinx-coroutines-jdk8 package中,默认不在core包中。
猜你喜欢
  • 2020-12-08
  • 2018-04-13
  • 2020-03-12
  • 2017-11-08
  • 2019-10-10
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
  • 2019-12-06
相关资源
最近更新 更多