Lleva Realm al siguiente nivel con Kotlin
Víctor Manuel Pineda

Cuando me preguntan qué es lo que más me gusta de Kotlin, siempre me resulta complicado quedarme con una sola característica.

Data classes, lambdas, inferencia de tipos, delegados… toda una serie de mejoras con respecto a Java que realmente marcan la diferencia en el día a día.

Descubriendo las extensiones en Kotlin


Sin duda, una de las características a las que más saco partido en mis proyectos Android son las extensiones.

La primera vez que oí hablar de este concepto me resultó cuanto menos extraño. La idea de añadir funciones a una clase sin necesidad de heredar de ella o sin tan siquiera tener acceso a ella me parecía poco útil e innecesaria.

¿Por qué iba a necesitar añadir código a clases fuera de mi alcance? Mi primera impresión no fue muy buena, y pensé que inevitablemente acabaría acarreando malas prácticas y un código difícil de entender.

Sin embargo, todas estas dudas se disiparon rápidamente cuando empecé a comprender toda la potencia que había detrás de una idea tan simple.

Ejemplos como poder cargar una imagen desde una url haciendo algo como imageView.loadFrom(url), pasar de dp a px escribiendo simplemente 10.toPx(context), o eliminar una vista de su padre haciendo view.removeFromParent() simplemente no tiene precio. Funciones que siempre me habría gustado tener en el SDK de Android, de repente encuentras la posibilidad de incluirlas tú mismo de forma que parece que realmente formen parte de él.

Realm conoce a Kotlin: la unión hace la fuerza

Todo ello es lo que me ha motivado a escribir una pequeña librería de extensiones para simplificar el uso de Realm.

Si lo has usado (y sufrido) alguna vez, sabrás que requiere de cierto boilerplate a la hora de trabajar con él. Además, tiene varias restricciones que complican su uso, como es el tener que abrir y cerrar instancias de Realm manualmente (y realizar ambas operaciones en el mismo hilo), no poder pasar los resultados de tus queries en background a la vista en el hilo principal sin antes desvincular los objetos de Realm, necesidad de abrir y cerrar transacciones para realizar una única operación…

Se trata de limitaciones que pueden resultar bastante tediosas, en las que hay que prestar atención para evitar futuros problemas.

Con esta librería, he pretendido convertir el API de Realm en lo que siempre me habría gustado que fuese. El objetivo que he perseguido es olvidar todas las limitaciones de Realm y trabajar a un nivel de abstracción mayor.

La librería en cuestión se llama Kotlin Realm Extensions, y puedes encontrarla en este enlace.

Su uso es realmente sencillo. En primer lugar, debes incluir la dependencia en tu fichero build.gradle:

compile 'com.github.vicpinm:krealmextensions:1.0.4'

En segundo lugar, debes saber lo que la librería va a hacer por ti:

  • Obtener la instancia por defecto de Realm y cerrarla tras finalizar la operación.
  • Iniciar y cerrar transacciones
  • Desvincular los objetos de Realm para poder trabajar con ellos en otros hilos.
  • Forzar la ejecución de queries que devuelven observables sobre el hilo principal (requisito para este tipo de consultas).

Por último, toca ponerse manos a la obra. Veamos algunos ejemplos de su uso:

Persistencia de una entidad con Java

User user = new User("John");

Realm realm = Realm.getDefaultInstance();
try{
   realm.beginTransaction();
   realm.copyToRealmOrUpdate(user);  
   realm.commitTransaction();
} finally {
   realm.close();
}

Equivalente con Kotlin Realm Extensions

User("John").save() 

También tenemos disponible el método saveAll() para arrays y colecciones.

Obtener todas las entidades de un tipo con Java

Realm realm = Realm.getDefaultInstance();
try {
    List events = realm.where(Event.class).findAll();
    events = realm.copyFromRealm(event);
} finally {
    realm.close();
}

Equivalente con Kotlin Realm Extensions

val events = Event().allItems

O también podemos realizar queries condicionales de forma sencilla:

val events = Event().query { it.equalTo("id",1) }

La expresión lambda recibe como parámetro una instancia de RealmQuery con la que podemos concatenar nuestras condiciones para realizar la query.

También podemos realizar nuestras queries a través de observables y escuchar cambios en los resultados en tiempo real. Esto resulta bastante tedioso con Realm:

Realm realm = Realm.getDefaultInstance();
Observable<List> obs =  realm.where(Event.class).findAllAsync()
    .asObservable()
    .filter(RealmResults::isLoaded)
    .map(realm::copyFromRealm)
    .doOnUnsubscribe(() -> realm.close());

Todo ello se reduce ahora a algo tan simple como:

val obs = Event().allItemsAsObservable

O bien:

val obs = Event().queryAsObservable { it.equalTo("id",1) }

Esta es una pequeña muestra del nivel al que puede llegar a simplificase tu código. Tienes toda la documentación disponible en la página de GitHub.

Conclusión

Como podemos ver, el uso de extensiones puede llegar a simplificar enormemente nuestro código en determinadas situaciones.

Sigo pensando que el empleo de extensiones debe hacerse con cabeza y no abusar de ellas. Pero un buen uso puede mejorar enormemente la legibilidad de nuestro código, y creo que esta librería es una buena muestra de ello.

Os animo a que la probéis y dejéis vuestra opinión.

Quizá también te interese…

Kotlin 1.5.0 : Las 5 novedades que puedes empezar a usar hoy

Kotlin 1.5.0 : Las 5 novedades que puedes empezar a usar hoy

Kotlin 1.5.0 ya está aquí, y como siempre trae una serie de novedades que te van a interesar muchísimo. Cabe destacar que a partir de ahora, de acuerdo las nuevas versiones de Kotlin se lanzarán cada 6 meses, independientemente de las nuevas funcionalidades que...

¿Qué es Kotlin y para qué sirve?

¿Qué es Kotlin y para qué sirve?

Kotlin es un lenguaje de programación de código abierto creado por JetBrains que se ha popularizado gracias a que se puede utilizar para programar aplicaciones Android. Pero si has llegado hasta aquí pensando que Kotlin solo se puede usar en Android, lo que te voy a...

2 formas de recolectar Flows en la UI que SÍ funcionan

2 formas de recolectar Flows en la UI que SÍ funcionan

En la serie de artículos sobre Programación Reactiva con Flow hemos visto muchos conceptos, y hemos aprendido cómo aplicarlos al desarrollo Android. Pero hay algo que no hemos hecho del todo bien. Esto es la recolección de Flows desde la Activity (o el Fragment, en...

0 comentarios

Enviar un comentario

Los datos personales que proporciones a través de este formulario quedarán registrados en un fichero de Antonio Leiva Gordillo, con el fin de gestionar los comentarios que realizas en este blog. La legitimación se realiza a través del consentimiento de la parte interesada. Si no se acepta, no podrás comentar en este blog. Los datos que proporciona solo se utilizan para evitar el correo no deseado y no se usarán para nada más. Puede ejercer los derechos de acceso, rectificación, cancelación y oposición en contacto@devexperto.com.

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

Acepto la política de privacidad *