Room, la librería de Base de datos de Android
Antonio Leiva

En este artículo te quiero mostrar cuáles son los pasos para empezar a utilizar la librería de Room.

Room es una librería de base de datos creada por el equipo de Android en Google y que simplifica la tarea de trabajar con bases de datos en Android.

Room es tan fácil de usar, que en unos minutos tendrás una base de datos lista para ser usada.

Cómo funciona

La librería de Room actúa de intermediaria con la App. Lo que hacemos es pedirle el DAO que queremos usar, y el DAO nos devuelve una serie de Entities, que podemos modificar para actualizar la base de datos.

Tampoco te líes mucho con los conceptos porque lo veremos en el ejemplo

Añadir las dependencias de Room

Necesitas incluir el plugin kotlin-kapt y las dos siguientes dependencias:

apply plugin: 'kotlin-kapt'

dependencies {
    implementation "androidx.room:room-ktx:2.2.5"
    kapt "androidx.room:room-compiler:2.2.5"
}

Como siempre, recuerda revisar las últimas versiones en la sección de releases de AndroidX.

Creamos las entidades que va a tener la base de datos

Si lo relacionamos con los conceptos típicos de una base de datos, estas entidades vendrían a ser las tablas.

Por ejemplo, si tenemos una entidad tipo persona como esta:

data class Person(
    val name: String,
    val age: Int,
    val address: String
)

Lo único que necesitamos es añadir la anotación @Entity para convertirlo en una entidad de Room:

@Entity
data class Person(
    val name: String,
    val age: Int,
    val address: String
)

Además, podemos añadirle un id que se autogenere, para identificar las distintas filas de la tabla:

@Entity
data class Person(
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    val name: String,
    val age: Int,
    val address: String
)

Y ya está, esto nos creará una tabla de base de datos, ahora necesitaríamos poder hacer peticiones sobre esta tabla.

DAOs (o Data Access Objects)

Son los objetos que nos van a permitir acceder a los datos. Utilizando la anotación @Dao es muy sencillo:

@Dao
interface PersonDao {
}

Los DAOs son interfaces, y cada método representa una operación de acceso o modificación de base de datos. Mediante anotaciones le indicamos qué operación van a realizar.

Acceso a datos

@Dao
interface PersonDao {

    @Query("SELECT * from Person")
    fun getAll(): List<Person>
}

Una cosa súper interesante es que Android Studio nos permite autocompletar y hacer validaciones sencillas de las queries que definimos:

A las queries también podemos pasarles argumentos. Solo tienes que indicar el argumento en la función, y lo podrás usar desde la query:

@Query("SELECT * FROM Person WHERE id = :id")
fun findById(id: Int): Person

Creación de nuevos registros

Se realizan mediante la anotación @Insert:

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(people: List<Person>)

Gracias a onConflict, le podemos definir la estrategia de inserción si hay conflictos: IGNORE, ABORT o REPLACE

Actualización de registros

Es igual de fácil, pero con la anotación @Update:

@Update
fun update(person: Person)

Borrado de registros

Como ya te puedes imaginar a estas alturas, se haría con la anotación @Delete:

@Delete
fun delete(person: Person)

Creación de la base de datos

Este paso es muy sencillo. Solo tienes que crear la base de datos de Room, e identificar qué entidades va a utilizar y que DAOs puede proveer.

Hay que definirla como una clase abstracta que extienda de RoomDatabse, y utilizar una serie de anotaciones que harán todo el trabajo sucio por nosotros:

@Database(
    entities = [Person::class],
    version = 1
)
abstract class PeopleDb : RoomDatabase() {

    abstract fun personDao(): PersonDao
}

Para crear la instancia de Room, en el Application por ejemplo (si no usas inyección de dependencias):

    val room: PeopleDb = Room
        .databaseBuilder(this, PeopleDb::class.java, "people")
        .build()

Y para usarlo:

val people = room.personDao().getAll()

Cómo evitar que Room se ejecute en el hilo principal

Todas estas operaciones de base de datos deberían hacerse fuera del hilo principal. Esto lo podemos hacer manualmente nosotros, o usar alguna de las integraciones que ya se nos dan implementadas.

Integración con corrutinas

Lo único que necesitamos es añadir la palabra suspend delante de las funciones del DAO, ¡y listo!

    @Query("SELECT * from Person")
    suspend fun getAll(): List<Person>

Soluciones reactivas

Quizá preferimos que se nos informe cada vez que se modifiquen los elementos de la Query realizada. Para ello, lo que podemos hacer es usar alguna de las integraciones que tenemos con:

  • LiveData
  • Flow de Corrutinas
  • RxJava
  • Guava

Por ejemplo, con LiveData, es tan sencillo como devolver el objeto envuelto en un LiveData:

    @Query("SELECT * from Person")
    suspend fun getAll(): LiveData<List<Person>>

Lo único que tendríamos que hacer sería observar ese LiveData.

Déjame en los comentarios si quieres que haga otro artículo hablando sobre alguna de las demás integraciones.

Y aquí puedes acceder al Gist con los distintos archivos.

Quizá también te interese…

3 formas de pasar varios Listeners a un RecyclerView

3 formas de pasar varios Listeners a un RecyclerView

Seguro que has visto muchos ejemplos donde un RecyclerView recibe un listener para, por ejemplo realizar, una acción cuando se hace click en el elemento. class MoviesAdapter(private val listener: (Movie) -> Unit) : ListAdapter<Movie, MoviesAdapter.ViewHolder>(...)...

Clases y constructores en Kotlin con Android Studio

Clases y constructores en Kotlin con Android Studio

Veremos un repaso las clases y constructores de Kotlin para solventar esas inquietudes que nos surgen a la hora de seguir este curso, que pueden ser como funciona realmente y porque se presentan las clases de ese modo, como es la interacción y el constructor a la hora...

Temas, colores, tipografías y formas en Jetpack Compose

Temas, colores, tipografías y formas en Jetpack Compose

Si vienes del sistema clásico de vistas, recordarás que toda la definición de temas se hacía de una forma bastante tediosa a través de styles en XML. Si odias tu vida (o estás en una App donde mezclas XMLs y Jetpack Compose), aún puedes seguir usando esos temas...

4 Comentarios

  1. Jorge Castellanos

    me gustaría preguntar ya que no he encontrado nadan en la red, estoy aprendiendo a usar el Room, ya he logrado implementarlo y funciona bien, pero mi duda es sobre el DAO @Update, es decir, to tengo un registro en la base, que se modifica constantenente con diferentes indicadores, el tema es que no siempre son los mismos indicadores que tengo que modificar, mi duda es, de que manera puedo elegir de la tabla que registro quiero modificar y cual no? el mismo id?

    Responder
    • Antonio Leiva

      Sí, si le pasas al update un objeto con el mismo id que el que quieres modificar, te actualiza esa fila de la tabla

      Responder
  2. carlos garcia

    Todos los ejemplos y tutoriales hablan de como crear una base Room. Mi pregunta es la siguiente, si estoy haciendo una base para guardar ciertas configuraciones por ejemplo. Como hago para utilizarla después, solo he encontrado ejemplos que me la vuelven a crear y toca llenarla desde cero, y esa no seria la idea. O el databaseBuilder puede «abrir» una base para consultar?

    Responder
    • Antonio Leiva

      Hola Carlos, una base de datos precisamente sirve para persistir información, así que no debería volver a crearse otra vez. En mi ejemplo, esa base de datos almacena lo que necesites, y luego puedes consultarlo. El builder crea el objeto para acceder a la base de datos, pero si el nombre se mantiene, la base de datos es la misma y tendrá los datos que hayas guardado previamente.

      Responder

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.

Acepto la política de privacidad *