Android 使用协程执行的 kotlin 任务

Android kotlin task to be executed using coroutines

例如,我正在使用 FusedLocationProviderClient 访问当前位置,return这是一个回调最终将 return 位置的任务。该方法如下所示:

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

是否可以对此进行转换,以便我可以使用协程来暂停此功能并等待 return 由 flpc.lastLocation 编辑的任务,以便我可以 return 在这种方法中这样就摆脱了那个回调?例如这样的事情:

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

我的问题是协程是否有一些东西可以让我 return Task 的结果(在这个例子中,Task<Location>

提前致谢!

kotlinx-coroutines-play-services library has a 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 调度程序上的线程,如果替代方案可用,则不应使用。

我采用的另一种方法也可以与任何回调类型接口一起使用,即使用 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))'
    }
}