Cómo usar LiveData con Realm

Si eres un desarrollador de Android y no has estado viviendo bajo una roca desde Google IO '17, sin duda has visto mucha emoción y numerosas publicaciones de blog con respecto a los componentes de arquitectura de Android.

De hecho, hay mucho de qué entusiasmarse con respecto al poder y la utilidad de estos nuevos componentes (ViewModel, Lifecycle, LiveData y Room).

Transmisión de datos en vivo

Desde mi perspectiva, LiveData es la parte más emocionante de la línea. Es increíble ver a Google ahora adoptando el concepto de datos en vivo y con actualización automática. Es igualmente sorprendente ver cómo han integrado LiveData directamente en el nuevo SQLite ORM (Room).

Esto facilita ver el poder de LiveData de inmediato, pero lo que más me gusta del diseño de LiveData es que Google lo ha hecho genérico y abierto para que los desarrolladores usen LiveData para una variedad de otros casos de uso como:

  • Gestión del estado de la red y conciencia
  • Devolución de LiveData w / Retrofit
  • Aplicación State Management

Realm + LiveData

¡La naturaleza flexible de LiveData le permite integrarse fácilmente en otras bibliotecas de terceros también! Como ingeniero en Realm, esto es muy emocionante para mí porque significa que puedo envolver RealmResults como LiveData y usarlo como lo haría con cualquier otra pieza de LiveData.

Esto tiene al menos dos beneficios adicionales.

Hace que sea aún más fácil para los desarrolladores reaccionar a los cambios de datos, ya que ya no tienen que registrar un changeListener para RealmResults en su método Activities onStart () y anular el registro en OnStop (). Más bien, esto puede suceder automáticamente con Realm-LiveData cuando la actividad propietaria comienza y deja de observarla.

El segundo beneficio es que permite que RealmResults participe en LiveData Transformations. Las transformaciones son geniales porque le permiten transformar cualquier LiveData de algo muy específico, como LiveData , en su capa de repositorio o ViewModel, a algo completamente agnóstico de la fuente subyacente, como LiveData en la capa de actividad. Obtiene esto sin renunciar a la naturaleza de actualización automática en vivo de Realm. Esto mantiene las diversas capas de su aplicación aisladas, lo que las hace más fáciles de componer, actualizar y probar.

Empezando

Para obtener una guía de instrucciones completa y un proyecto de muestra sobre cómo integrar componentes de arquitectura en Realm, consulte esta otra publicación que escribí, pero este ejemplo rápido debería darle la idea general para comenzar.

1. Cree un contenedor LiveData para sus RealmResults.

// Esto funciona para los resultados de cualquier RealmModel en su proyecto
public class RealmLiveData  extiende LiveData > {
resultados de RealmResults privados ;
    privado final RealmChangeListener > listener =
        nuevo RealmChangeListener > () {
            @Anular
            public void onChange (RealmResults  resultados) {
                setValue (resultados);
            }
    };
    public RealmLiveData (RealmResults  realmResults) {
        resultados = realmResults;
    }
    @Anular
    nulo protegido en Active () {
        results.addChangeListener (escucha);
    }
    @Anular
    vacío protegido en inactivo () {
        results.removeChangeListener (escucha);
    }
}

2. Úselo para envolver RealmResults expuestos de su capa Realm Dao o Repository.

public RealmLiveData  findLoansByNameAfter (String userName, Date after) {
    regresar como LiveData (realm.where (Loan.class)
            .like ("user.name", userName)
            .greaterThan ("endTime", después)
            .findAllAsync ());
    // Async ejecuta la búsqueda desde el hilo principal y devuelve
    // resultados como LiveData de nuevo en el main.
}

3. Finalmente, úselo como lo haría con cualquier otro LiveData en su ViewModel, asignándolo a algo más genérico para su capa de Actividad, y suscríbase a él desde su Actividad.

// ViewModel
clase pública LoanViewModel extiende ViewModel {
    reino del reino privado;
    
    préstamos públicos de LiveData ;
    // Actividad suscrita a LiveData 
    privado vacío subscribeToMikesLoansSinceYesterday () {
        RealmLiveData  préstamos = préstamo de préstamos (reino)
                 .findLoansByNameAfter ("Mike", getYesterdayDate ());
        préstamos = Transformaciones.map (préstamos, nueva Función () {...});
    }
    ...
}
// Actividad
LoanActivity de clase pública extiende LifecycleActivity {
  
    vacío protegido onCreate (Bundle savedInstanceState) {
        ...
        viewModel.loans.observe (this, new Observer  () {
            public void onChanged (resultado de cadena) {
                updateUI (resultado)
            }
        });
       ...
    }
   ...
}

4. (Opcionalmente) ¡Rocía un poco de Kotlin y es como si los Componentes de Arquitectura de Android hubieran estado allí todo el tiempo!

// Usar como
// realm.loanDao () en Kotlin
// prestatario (reino) en Java
Fun Realm.loanDao (): LoanDao = LoanDao (this)
// Usar como
// realmResults.asLiveData () en Kotlin
// nuevo RealmLiveData (reino) en Java
diversión  RealmResults  .asLiveData () = RealmLiveData  (esto)

Impacto de los componentes de arquitectura

Lo que esto significa para los desarrolladores que aman a Realm por su API simple, su rico sistema de notificaciones y la sincronización de datos en tiempo real entre dispositivos, es que todas las grandes partes de los componentes de arquitectura de Android, ViewModels, Lifecycle, LiveData e incluso acceso a datos encapsulados a través de DAO están disponibles sin renunciar a las características que han llegado a amar!