Skip to content

Instantly share code, notes, and snippets.

@gildor
Created August 15, 2020 03:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save gildor/7aca7499632056235cf7c8b3b3d92e29 to your computer and use it in GitHub Desktop.
Save gildor/7aca7499632056235cf7c8b3b3d92e29 to your computer and use it in GitHub Desktop.
Kotlin coroutines adapter for google-maps-services-java (Google Maps API client)
import com.google.maps.GeoApiContext
import com.google.maps.GeocodingApi
import com.google.maps.PendingResult
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
/**
* Coroutine adapter for Google Maps API future type [PendingResult]
*
* Can be used to perform asynchronous non-blocking calls to any Google Maps APIs
*
* Name of extension [awaitAsync] is chosen to avoid conflict with
* a member method [PendingResult.await] which is a blocking API of [PendingResult]
*/
suspend fun <T> PendingResult<T>.awaitAsync(): T = suspendCancellableCoroutine { cont ->
cont.invokeOnCancellation {
cancel()
}
setCallback(object : PendingResult.Callback<T> {
override fun onResult(result: T) {
cont.resume(result)
}
override fun onFailure(e: Throwable) {
cont.resumeWithException(e)
}
})
}
/**
* Example of usage of [awaitAsync] extension to perform Geocoding request
*/
suspend fun main(args: Array<String>) {
val apiKey = requireNotNull(args.elementAtOrNull(0)) {
"First argument `API key` is not specified"
}
val address = requireNotNull(args.elementAtOrNull(1)) {
"Second argument `Address` is not specified"
}
val result = GeocodingApi.geocode(
GeoApiContext.Builder().apiKey(apiKey).build(),
address
).awaitAsync().orEmpty()
println(result.contentToString())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment