android - Kotlin 和 Anko 协程 : return outside async

标签 android kotlin anko

在我们的项目中,我们需要在进行操作之前获取一些数据(这些数据将被存储)。如果数据是在 15 分钟前获取的,我们必须刷新它。

我们使用 Kotlin + Anko 协程来做到这一点。这个想法(假设数据是在之前的某个时刻获得的)是:

该方法被调用并检查我们何时获得数据。 如果不到 15 分钟,则返回。 如果没有,则异步获取(这是一个网络操作),存储并返回。

由于在获取刷新的数据之前我们无法做任何事情,因此刷新必须是同步的(尽管网络操作本身是异步的)。

我们有这个代码:

fun Context.retrieveInfo(api: Api?): User? {

  try {

    // For sake of simplification the real conditional check is removed
    if (time > 15) {

        val context = this
        val asyncUser = async(UI) {
            val obtainData: Deferred<Data?> = bg {
                api?.obtainData(sphelper.getDefaultUser(context))
            }

            val obtainedData = storeAndRetrieve(obtainData.await(), context)
            return@async obtainedData
        }

 // ???????

    } else {
        val input = ObjectInputStream(this.openFileInput("data.dat"))
        return input.readObject() as Data
    }
  } catch (e: Exception) {
    return null
  }
}

我们如何让函数在 async(UI) block 之外等待结果?该返回是需要的,但我们不知道应该在那里放什么。我们尝试过 Deferred 对象的 getCompleted() 方法(返回 asyncUser.getCompleted()),但最终崩溃,因为它返回 null。

谢谢!

最佳答案

我看到有几种方法可以做到这一点。一种是使用 kotlinx.coroutines.experimental 方法 runBlocking:

val user = runBlocking(CommonPool) {
    val asyncUser = async(UI) {
        val obtainData: Deferred<String> = bg {
            ...
        }

        val obtainedData = storeAndRetrieve(obtainData.await(), context)
        return@async obtainedData
    }
    return@runBlocking asyncUser.await()
}

根据用例,您甚至可以将其简化为:

val asyncUser = runBlocking {
    async(CommonPool) {
        val obtainedData = storeAndRetrieve(api?.obtainData(sphelper.getDefaultUser(context)), context)
        return@async obtainedData
    }.await()
}

另一种方法是使用基本的 Java CountDownLatch:

var asyncUser: String? = null
val c = CountDownLatch(1)
async(UI) {
    val obtainData: Deferred<String> = bg {
        ...
    }

    val obtainedData = obtainData.await()
    asyncUser = obtainedData
    c.countDown()
}
c.await()

关于android - Kotlin 和 Anko 协程 : return outside async,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46197077/

相关文章:

kotlin - 如何将自定义 View 组添加到 Anko DSL?

Android 进度条删除默认填充

java - 如何在Android中获取带有按钮的项目信息

dictionary - 如何在 Kotlin 中反转 map ?

android - Kotlin Coroutines - 从 Coroutine 返回一个值而不阻塞主线程 Android

android - 如何在任何 Jetpack Compose View 上禁用涟漪效应?

android - 如何在 anko 中创建标签 View

android - Kotlin/Anko 按钮 onClick 不起作用

android - Android 阿拉伯字母的 keyCodes

android - 通过调用号码取消隐藏 Android 应用程序