简体   繁体   English

使用协程执行的 Android kotlin 任务

[英]Android kotlin task to be executed using coroutines

As an example, I'm using FusedLocationProviderClient to access the current location, which returns a task which callback will eventually return the location.例如,我使用 FusedLocationProviderClient 访问当前位置,它返回一个任务,回调最终将返回该位置。 The method looks something like follows:该方法如下所示:

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

Is it possible to transform this so that I can use corroutines to suspend this function and wait for the task returned by flpc.lastLocation so I can return it in this method and this way get rid of that callback?是否可以对其进行转换,以便我可以使用 corroutines 挂起此函数并等待flpc.lastLocation返回的任务,以便我可以在此方法中返回它并以这种方式摆脱该回调? For example something like this:例如这样的事情:

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

My question is if there is something around coroutines where I can return the result of a Task (in this example, a Task<Location> )我的问题是,协程是否可以返回Task的结果(在本例中为Task<Location>

Thanks in advance!提前致谢!

The kotlinx-coroutines-play-services library has a Task<T>.await(): T helper. kotlinx-coroutines-play-services库有一个Task<T>.await(): T helper。

import kotlinx.coroutines.tasks.await

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

Alternatively take a look at Blocking Tasks或者看看阻塞任务

It would be used the next way:它将以下一种方式使用:

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
    }

Just to add to this example, for completion purposes, the call to getLocation() would be done the next way:只是为了添加到这个例子中,为了完成目的,对getLocation()的调用将通过以下方式完成:

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

However this negates the benefits of coroutines by not leveraging the available callback and blocking a thread on the IO dispatcher and should not be used if the alternative is available.然而,这通过不利用可用回调和阻塞 IO 调度程序上的线程来否定协程的好处,如果替代方案可用,则不应使用协程。

Another way that I have don this that can also be used with any callback type interface is to use suspendCoroutine<T> {} .我这样做的另一种方法也可以与任何回调类型接口一起使用是使用suspendCoroutine<T> {}

So for this example it would be:所以对于这个例子,它将是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM