¿Cómo observar el evento solo una vez usando SingleLiveEvent en Android?

¿Alguna vez ha tenido que lidiar con un Diálogo o un SnackBar que, después de activarse, mostrarse o descartarse, se vuelve a activar/mostrar después de una rotación del dispositivo? Lo más probable es que esto esté relacionado con el uso de observables LiveData para comunicarse entre ViewModel y Activity/Fragment .

El patrón es lo opuesto

El uso de objetos LiveData para eventos puede verse como una mala elección de diseño, especialmente cuando el evento solo se requiere una vez. Podemos usar algunos indicadores booleanos para ayudar a la vista a determinar si el Diálogo/SnackBar se debe activar/mostrar o no. Sin embargo, esto podría resultar en una solución que es difícil de comprender y mantener, además de ser poco atractiva. Como puedes ver tiene el tipo de datos en vivo, los datos se consumen continuamente, pero solo queremos obtenerlos una vez .

No hay pérdidas de memoria:

Los observadores están vinculados a los objetos del ciclo de vida y se limpian cuando se destruye el ciclo de vida con el que están conectados.

No se han producido accidentes por paralización de la actividad:

Si el tiempo de vida del observador está inactivo, como en el caso de una actividad de back stack, no recibe ningún evento LiveData. LiveData simplemente sigue el diseño del observador, y no creo que el caso de uso mencionado anteriormente garantice su propia variante de la clase observable. Entonces, ¿cómo podemos resolver el tema del diálogo? En lugar de alterar el comportamiento de LiveData, debemos mantener los conceptos básicos del paradigma MVVM y, si es necesario, hacer que ViewModel le informe a ViewModel sobre el diálogo descartado. Después de eso, la VM podría restablecer o alterar el estado del evento. Me doy cuenta de que es fácil olvidar alertar a ViewModel y estamos aumentando las responsabilidades de View. Pero, después de todo, es el trabajo de View: informar a la VM de cualquier acción del usuario.

¿Cómo lograr esto?

Cree una clase de ‘Evento’ que sea general (tal vez llámela LiveEvent). Dale las funciones observe (propietario, observador) y observeForever (observador). Dale el mismo contrato y funcionalidad que LiveData. Excepto que, en lugar de un valor persistente, LiveEvent solo notifica a los observadores activos mientras se envía junto con los datos.

Kotlin

class LiveEvent<C> {
...
  fun sendingValue(data: C) {
    observers.forEach { gfg ->
      if (gfg.isActive()) gfg.onChanged(data)
    }
  }
}

Coloque LiveEvent en su clase básica de ViewModel si desea utilizarlo para publicar notificaciones, SnackBars o cualquier cosa en muchas pantallas. Luego, después de inicializar ViewModel en su clase Fragment básica, observe ese LiveEvent.

Kotlin

abstract class GeeksforGeeksViewModel : ViewModel() {
  protected val fireAlertedEvent = LiveEvent<FireAlert>()
}
abstract class BaseFragment : Fragment() {
  fun onViewModelInitialized() {
    viewModel.fireAlertedEvent.observe(this, { fireAlert ->
      fireAlert.show()
    }
  }
}
class GeeksforGeeksSample : GeeksforGeeksViewModel() {
  fun onSaveSuccess() {
    fireAlertedEvent.postValue(FireAlert("yay! we got your stuff!"))
  }
}

Conclusión

La solución óptima sería una fuente de eventos con cancelación de suscripción automática en caso de destrucción que ponga en cola los eventos siempre que no haya observadores presentes y luego envíe todos los eventos al primer observador que se suscriba. Eso puede manejar los eventos de la manera que considere adecuada. Cuando necesita administrar el flujo, usar una devolución de llamada con distintos métodos de éxito/fracaso es una idea terrible. Hacer uso de un ADT (clase sellada).

Publicación traducida automáticamente

Artículo escrito por therebootedcoder y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

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