【问题标题】:Android kotlin task to be executed using coroutines使用协程执行的 Android kotlin 任务
【发布时间】:2019-12-10 14:09:54
【问题描述】:

例如,我使用 FusedLocationProviderClient 访问当前位置,它返回一个任务,该回调最终将返回该位置。该方法如下所示:

fun getLocation(callback: MyCallback){
    val flpc = LocationServices.getFusedLocationProviderClient(it)
    flpc.lastLocation.addOnSuccessListener {
        callback.onLocation(it)
    }
}

是否可以对其进行转换,以便我可以使用协程挂起此函数并等待flpc.lastLocation 返回的任务,以便我可以在此方法中返回它,从而摆脱该回调?例如这样的:

suspend fun getLocation(): Location? =
    withContext(Dispachers.IO){
        val flpc = LocationServices.getFusedLocationProviderClient(it)
        return@withContext flpc.lastLocation.result()
    }

我的问题是协程周围是否有什么东西可以返回 Task 的结果(在本例中为 Task<Location>

提前致谢!

【问题讨论】:

标签: android task kotlin-coroutines


【解决方案1】:

kotlinx-coroutines-play-services 库有一个 Task<T>.await(): T 助手。

import kotlinx.coroutines.tasks.await

suspend fun getLocation(): Location? = 
    LocationServices.getFusedLocationProviderClient(context).lastLocation.await()

或者看看Blocking Tasks

接下来会用到:

suspend fun getLocation(): Location? =
    withContext(Dispachers.IO){
        val flpc = LocationServices.getFusedLocationProviderClient(context)
        try{
            return@withContext Tasks.await(flpc.lastLocation)
        catch(ex: Exception){
            ex.printStackTrace()
        }
        return@withContext null
    }

添加到这个示例中,为了完成目的,对getLocation() 的调用将通过以下方式完成:

coroutineScope.launch(Dispatchers.Main) {
    val location = LocationReceiver.getLocation(context)
    ...
}

然而,这抵消了协程的好处,因为它没有利用可用的回调并阻塞 IO 调度程序上的线程,如果有替代方案,则不应使用。

【讨论】:

    【解决方案2】:

    另一种可以与任何回调类型接口一起使用的方法是使用suspendCoroutine<T> {}

    所以对于这个例子,它会是:

    suspend fun getLocation(): Location? {
        return suspendCoroutine<Location?> { continuation ->
            val flpc = LocationServices.getFusedLocationProviderClient(it)
            flpc.lastLocation.addOnSuccessListener { location ->
                continuation.resume(location)
            }
            // you should add error listener and call 'continuation.resume(null)'
            // or 'continuation.resumeWith(Result.failure(exception))'
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-07
      • 1970-01-01
      • 2020-02-13
      • 2020-10-07
      • 1970-01-01
      • 2021-12-08
      • 2018-07-19
      相关资源
      最近更新 更多