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()
- Android – 显示集群项目单击信息窗口(标题)
- Anko日志与详细和调试不起作用
- Android Studio和Kotlin:未解决的参考:也
- RxJava Kotlin如何从单个可观察<String>中获得分离的对象
- Kotlin的Android扩展和变量
- Kotlin Android Studio / IntelliJ“可以加入任务”检查警告
- 为什么Kotlin插件为Android项目添加了kotlin-stdlib-jre7(不是kotlin-stdlib)参考
- 在kotlin中打开alertDialog,如何设置单选按钮的消息
- Kotlin Dokka – 在android studio中找不到Dokka任务