【问题标题】:Use property as accessor for Kotlin Coroutine使用属性作为 Kotlin 协程的访问器
【发布时间】:2019-10-01 13:39:12
【问题描述】:

Kotlin Coroutines 问题...挣扎着使用属性而不是函数作为异步调用的访问器。

背景是我正在尝试将FusedLocationProviderClientkotlinx-coroutines-play-services 库一起使用,以便在Task 上使用.await() 方法而不是添加回调...

目前有一个属性 getter 被踢出一个挂起函数,但不确定如何正确启动协程以避免

找到所需的单位 XYZ

错误...

 val lastUserLatLng: LatLng?
        get() {
            val location = lastUserLocation
            return if (location != null) {
                LatLng(location.latitude, location.longitude)
            } else {
                null
            }
        }

    val lastUserLocation: Location?
        get() {
            GlobalScope.launch {
                return@launch getLastUserLocationAsync()  <--- ERROR HERE
            }
        }

    private suspend fun getLastUserLocationAsync() : Location? = withContext(Dispatchers.Main) {
        return@withContext if (enabled) fusedLocationClient.lastLocation.await() else null
    }

关于如何处理这个问题有什么想法吗?

【问题讨论】:

  • 使用异步而不是启动

标签: android kotlin kotlin-coroutines fusedlocationproviderapi


【解决方案1】:

属性不能是异步的。一般来说,您不应该同步异步调用。当你需要一个值时,你必须返回一个Deferred 并调用await()

val lastUserLatLng: Deferredd<LatLng?>
    get() = GlobalScope.async {
        lastUserLocation.await()?.run {
            LatLng(latitude, longitude)
        }
    }

val lastUserLocation: Deferred<Location?>
    get() = GlobalScope.async {
        getLastUserLocationAsync()
    }

private suspend fun getLastUserLocationAsync() : Location? = withContext(Dispatchers.Main) {
    return@withContext if (enabled) fusedLocationClient.lastLocation.await() else null
}

但从技术上讲这是可能的,尽管您应该这样做。 runBlocking() 阻塞直到一个值可用并返回它。

【讨论】:

  • 嗯。谢谢。这可行,但我希望——也许是天真地——不必在我的代码中使用Deferred 值上的.await()(在这种情况下,我正在将协程引入遗留代码库......)
  • 无论如何你都必须这样做。但可以将其写入一个属性并在后台更新它。如果你经常使用它,它可能一样好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2021-11-18
  • 2020-11-21
相关资源
最近更新 更多