As an example, I'm using FusedLocationProviderClient to access the current location, which returns a task which callback will eventually return the location. 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? 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>
)
Thanks in advance!
Manage long-running tasks Coroutines build upon regular functions by adding two operations to handle long-running tasks. In addition to invoke (or call ) and return , coroutines add suspend and resume : suspend pauses the execution of the current coroutine, saving all local variables.
A coroutine is a concurrency design pattern that you can use on Android to simplify code that executes asynchronously. Coroutines were added to Kotlin in version 1.3 and are based on established concepts from other languages.
ViewModel + LiveData You could use a MutableLiveData like so: But, since you will be exposing this result to your view, you can save some typing by using the liveData coroutine builder which launches a coroutine and lets you expose results through an immutable LiveData. You use emit() to send updates to it.
Coroutine Scope A CoroutineScope keeps track of any coroutine it creates using the builder functions launch or async . It provides the ability to cancel a coroutine at any point in time. The scope is nothing but a lifespan. A coroutine cannot be launched without scope.
The kotlinx-coroutines-play-services
library has a 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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With