Ubicación del dispositivo utilizando el componente LiveData Architecture | autor: Айбек Ногоев | Octubre de 2020

En esencia, esta idea del artículo surgió después de que me resultara difícil implementar la lógica de detección de posición sin violar la arquitectura de la aplicación.

Después de varias horas de investigación, finalmente encontré una solución para rastrear mi ubicación actual usando LiveData. Te mostraré esta solución paso a paso.

Paso 1. Agregue dependencias para el detector de ubicación en el módulo gradle

implementation 'com.google.android.gms:play-services-location:x.x.x'

Paso 2. Crea un detector de ubicación

class LocationListener private constructor(private val context: Context): LiveData<Location?>()

Heredar una clase de LiveData

LiveData son datos observables clase de titulares. A diferencia de LiveData observable convencional, tiene en cuenta el ciclo de vida, lo que significa que respeta el ciclo de vida de otros componentes de la aplicación, como actividades, fragmentos o servicios. Esta conciencia asegura que LiveData solo actualiza a los observadores de los componentes de la aplicación que se encuentran en un estado de ciclo de vida activo.

El siguiente es un ejemplo completo de la clase Location Listener:

class LocationListener private constructor(private val context: Context): LiveData<Location?>() {
var requestingLocationUpdates: Boolean = true
private var mFusedLocationClient
: FusedLocationProviderClient? = null
private var mLocationRequest
: LocationRequest? = null@Synchronized
private fun createLocationRequest() {
Log.d(TAG, "Creating location request")
mLocationRequest = LocationRequest.create()
mLocationRequest?.interval = 20000
mLocationRequest?.fastestInterval = 5000
mLocationRequest?.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}

fun startService() {
onActive()
}

override fun onActive() {
super.onActive()
if (ActivityCompat.checkSelfPermission(
context, Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationProviderClient
createLocationRequest()
val looper = Looper.myLooper()
mFusedLocationClient?.requestLocationUpdates(mLocationRequest, mLocationCallback, looper)
}

override fun onInactive() {
if (mFusedLocationClient != null) {
mFusedLocationClient?.removeLocationUpdates(mLocationCallback)
}
}

val fusedLocationProviderClient: FusedLocationProviderClient?
get() {
if (mFusedLocationClient == null) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
}
return mFusedLocationClient
}

private val mLocationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
val newLocation = locationResult.lastLocation
if (newLocation != null && requestingLocationUpdates){
value = newLocation
onInactive()
}
}
}

companion object {
private const val TAG = "LocationListener"
private var instance
: LocationListener? = null
fun
getInstance(appContext: Context): LocationListener? {
if (instance == null) {
instance = LocationListener(appContext)
}
return instance
}
}

}

Entonces, lo que hicimos básicamente:

  • compilar FusedLocationProviderClient
  • crear una solicitud de ubicación
  • crear un looper
  • solicitar actualizaciones de ubicación

Una vez que comenzamos a solicitar actualizaciones de ubicación, Google Services le dice a la aplicación que sepa cada vez que cambia la ubicación. En este ejemplo, deshabilité las actualizaciones de ubicación una vez que se encontraron

override fun onLocationResult(locationResult: LocationResult) {
val newLocation = locationResult.lastLocation
if (newLocation != null && requestingLocationUpdates){
value = newLocation
onInactive() //Disable location updating
}
}

Es posible utilizar un detector de ubicación en el modelo de visualización, lo que facilita el uso del resultado de los servicios de ubicación.

Por ejemplo:

class LocationVM: ViewModel() {

var location: MutableLiveData<Location>? = MutableLiveData<Location>()
var locationRepository: LocationListener? = null

fun setLocationRepository(context: Context) {
locationRepository = LocationListener.getInstance(context)
}

fun enableLocationServices(){
locationRepository?.let {
it
.startService()
}
}
}

Paso 3. Para que esto funcione, debemos crear un observador.

Observador para oyentes:

viewModel.locationRepository?.let {
if
(!it.hasObservers()) {
it.observe(this, Observer<Location?> { location ->
location?.let {
viewModel
.location?.value = it
progress_bar.visibility = View.INVISIBLE
}
}
)
}
}

Observador de datos variables en vivo:

val locationObserver = Observer<Location> { location ->
// Update the TextView "location_text" text
Log.i("LiveData location", "" + location.latitude + " / " + location.longitude)
location?.let {
location_text.text = "" + it.latitude + "n" + it.longitude
}
}
viewModel
.location?.observe(this, locationObserver)

Y eso es todo.

Eche un vistazo a un proyecto de muestra en github https://github.com/Vicrisbeka/LocationMVVM/

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *