Firebase en la nube & Room en el móvil

Jhonny Ventiades
4 min readSep 19, 2019

El titulo de este articulo puede ser algo engañoso y confuso, dado que Firebase y Room nos ayudan a almacenar la información en base de datos se hace difícil de entender el por que utilizar ambos al mismo tiempo. El objetivo es unir estos dos mundos utilizando Firebase como un servicio para leer y escribir la data en la nube, y esta información sera guardará en una base de datos local con la ayuda de Room, esta combinación se enfoca en casos particulares que mencionaré en adelante.

Un poco repasando los conceptos y características de estas dos herramientas podemos mencionar:

Firebase utilizando Cloud Firestore o Realtime Database nos permite, en resumen, almacenar nuestra información en su base de datos en la nube como documentos y colecciones, Firebase se encarga de la persistencia de los datos, la conexión, subida y bajada de los datos con tan solo realizar breves configuraciones y utilizando sus métodos.

Room, en resumen, es una librería que abstrae todo el código técnico y repetitivo al momento de trabajar con una base de datos local(Conexión, lectura de tuplas, métodos de inserción/actualización).

¿El problema de usar Firebase?

Repasando las características de Firebase, es completamente suficiente para utilizarlo para almacenar la información local y en la nube, incluso con su modo de persistencia offline cubre gran parte de los casos reales al momento de desarrollar una aplicación, pero existen algunas razones por las cuales Firebase puede no satisfacer nuestras necesidades al momento de trabajar localmente, y estas razones se resumen en (Complejidad, Dinero):

  1. Transacciones COMPLEJAS: Muchas veces tenemos que realizar unión de diferentes colecciones de datos, o filtrados por mas de un tipo de campo, y es acá donde Firebase al ser tan simple de usar, nos limita en la manipulación de los datos, y se que muchos estarán acostumbrados como yo a SQL y verán mas cómodo realizar una consulta.
  2. El DINERO es limitado: Los servicios de Firebase son gratuitos, siempre y cuando no pases la cuota de conexiones simultaneas, tamaño en disco, etc., puede llegar a ser muy fácil pasar los limites gratuitos de Firebase si no cuidamos bien la subida y descarga de información, y esto puede ser complicado ya que Firebase se encarga solo de la persistencia de la información en la nube.

Existen muchos otros puntos que se pueden mencionar, pero estos son los mas relevantes para este articulo.

La solución

Para resolver los problemas mencionados y poder realizar transacciones complejas con nuestra información y al mismo tiempo cuidar de no sobrepasar los limites gratuitos de Firebase, implementaremos Firebase como servicio que descargara la información de la nube y la guardará en la base de datos local con Room, de esta forma:

  • Guardaremos la fecha de actualización de la base de datos local, es decir este registro sera único y cada que hagamos una descarga o subida de archivos actualizaremos este campo
  • Cada registro tendrá una fecha asignada que indica la fecha de edición del documento el cual se comparará con la ultima fecha de actualización de la base de datos local, si la fecha de la base de datos es menor a la fecha del documento en Firebase realizamos una descarga de los documentos que actualizaremos. De esta forma solo actualizaremos los datos que necesitemos actualizar y el consumo de transferencia de datos de Firebase será menor.
  • Si seguimos la arquitectura de Android, alojaremos los servicios de Firebase en la clase tipo Repository, de esta forma tendremos mas cuidado de que el llamado para la descarga de información sea a demanda.

Paso 1. Declaramos las entidades

La clase info guardará la información de la ultima actualización de la base de datos

@Entity
data class Info(
@PrimaryKey
@NonNull
var id: Long,
var lastUpdate: Long
)

La siguiente clase sera un ejemplo de los datos mínimos que debemos almacenar

open class MyObject constructor():Serializable {
@PrimaryKey
@NonNull
var id: String = ""
var updatedDate :Long = 0
var createdDate :Long = 0
var deleted: Boolean = false
}

updateDate: sera la ultima fecha de actualización de cada documento en firebase

deleted: Nos dirá si un documento fue eliminado tanto para notificar a firebase de ello.

Paso 2. Obtenemos los documentos nuevos o editados de firebase filtrados

val info= new InfoDao().get()
val toUpdate : MutableList<Topic> = ArrayList()
val db = FirebaseFirestore.getInstance()
val docRef = db.collection("myCollection")
docRef.whereGreaterThan("updateDate", info.lastUpdate).get().addOnCompleteListener {
if (it.isSuccessful) {
if(it.result != null) {
for (document in it.result!!) {
toUpdate
.add(document.toObject(MyObject::class.java))
}
saveDocuments(toUpdate)
}
}
}

Obtendremos los documentos filtrando solo por fecha mayor a la ultima actualización de nuestra tabla.

Paso 3. Guardamos los nuevos documentos con Room

val myDAO= AppDataBase.getAppDataBase(this@MainActivity).dMyObject()//realizamos un upsert para nuevos registros y actualizaciones
val rowIDs = myDAO.insert(documents)
val toUpdate = rowIDs.mapIndexedNotNull { index, rowID ->
if (rowID == -1L) documents[index] else null
}
toUpdate.forEach { myDAO.update(it) }
//realizamos la actualización de la tabal info al terminar de guardar todos los datos
info.lastUpdate = Date().time
infoDao.update(info)

Realizamos el guardado de la nueva información en la base de datos local y luego actualizamos la fecha de de referencia de nuestra tabla.

Listo, este método lo llamamos cada que deseemos actualizar la información. para el método de envió realizamos el mismo procedimiento pero de manera inversa.

Gracias por seguir hasta acá, si te interesa aprender más sobre firebase y android te invito a escuchar mi Podcast Declarando Variables

--

--