Last active
April 14, 2023 12:28
-
-
Save psteiger/75e683b89b3ea82ff2047cb3c140e666 to your computer and use it in GitHub Desktop.
Location-related Kotlin extension functions for Android.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Location-related Kotlin extension properties for Android. | |
// They must be implemented in an Activity because Geocoder needs a context. | |
// Or else, they must be turned from extension properties to extension functions that receive a context as parameter. | |
// Example of use | |
// Use case: show the user his locality name on a TextView | |
val userLocation = Location(someLatitude, someLongitude) | |
launch(UI) { | |
aTextView.text = userLocation.localityName.await() | |
} | |
// Returns list of addresses of a given LatLng. Uses Kotlin Coroutines. Does networking - don't use getFromLocation on UI thread. | |
// private because you probably want other higher-level values (e.g. LatLng.localityName) | |
private val LatLng.getAddresses: Deferred<List<Address>?> | |
get() = async { | |
try { | |
Geocoder(this@MainActivity, Locale.getDefault()).getFromLocation(latitude, longitude, 1) | |
} catch (_: IOException) { | |
null | |
} | |
} | |
// Returns a locality name (most commonly, a city name) given a LatLng. Uses Kotlin Coroutines. | |
val LatLng.localityName: Deferred<String?> | |
get() = async { getAddresses.await()?.firstOrNull()?.locality } | |
// Returns an ISO 3166 country code given a LatLng. Uses Kotlin Coroutines. | |
val LatLng.countryCode: Deferred<String?> | |
get() = async { getAddresses.await()?.firstOrNull()?.countryCode } | |
// Returns the country name given a LatLng. Uses Kotlin Coroutines. | |
val LatLng.countryName: Deferred<String?> | |
get() = async { getAddresses.await()?.firstOrNull()?.countryName } | |
// Converts Location object to LatLng object | |
val Location.latLng | |
get() = LatLng(latitude, longitude) | |
// Avoids having to call location.latLng.localityName - instead call location.localityName | |
val Location.localityName: Deferred<String?> | |
get() = latLng.localityName | |
// Avoids having to call location.latLng.countryCode - instead call location.countryCode | |
val Location.countryCode: Deferred<String?> | |
get() = latLng.countryCode | |
// Avoids having to call location.latLng.countryName - instead call location.countryName | |
val Location.countryName: Deferred<String?> | |
get() = latLng.countryName |
@dmytrodanylyk your approach works, but if you would use getAddresses directly, you’d get an exception (networking on UI thread)
Async on getAddresses makes it safe. This safety makes up (for me) for the very small overhead of creating an extra unnecessary coroutine.
github full working?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Why do you create two coroutines, while you can use one?