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 } } 

我们如何才能使该功能等待异步(UI)块之外的结果呢? 这个回报是必要的,但我们不知道应该在那里放什么。 我们已经尝试了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()