9

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!

2

2 Answers 2

15

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.

Sign up to request clarification or add additional context in comments.

Comments

1

Another way that I have done this that can also be used with any callback type interface is to use 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))' } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.