Browse Category

Realm

realm_header

Almacenamiento en Android: Realm como base de datos

Introducción

Como casi todos sabréis, el almacenamiento en android puede dividirse en 3 grandes grupos: preferencias, ficheros y bases de datos. Estas ultimas son las que mas se utilizan en el desarrollo de aplicaciones para persistir datos, en especial SQLite. Gracias a distintos ORM’s (OrmLite, GreenDao, SQLBrite,..), el desarrollo en este tipo de base de datos se ha simplificado.
Durante los últimos tiempos, se ha popularizado el uso de un nuevo tipo de base de datos, el cual no es un ORM de SQLite, sino un gestor propio: REALM

¿Por qué debo usar Realm?

  • Realm es una base de datos muy fácil de usar. En cuestión de minutos puedes tener tu aplicación funcionando con la base de datos. Realm no es un ORM ni un wrapper sobre SQLite. En vez de esto, contiene su propio motor de persistencia
  • Realm es muy rápido.Cuando digo rápido es realmente rápido. En un segundo puede insertar 20.000 registros, por los 9.000 de SQLite, 5.000 de ORMLite, y los apenas 2.000 de GreenDao. Las queries y el conteo de registros, mas veloz aun, sacándole mas ventaja a sus seguidores.

realm_android_insertsrealm_android_queries

  • realm_android_countsRealm es multi-plataforma, por lo que si en vuestro proyecto estáis desarrollando tanto versiones de android como de iOS, podéis optar por este mismo gestor de base de datos. Para iOS, está desarrollado para swift y para objective-c.
  • Realm permite un uso avanzado de la base de datos, pudiendo cifrarse fácilmente, además de poder modificar las políticas de migración de versiones.

Configurar Realm en nuestro proyecto Android

La versión que vamos a utilizar es la 0.88.3. Para utilizar este gestor de base de datos, debemos asegurarnos de que cumplimos los requisitos mínimos. En esta versión de Realm, se necesita:

  • Versión de Android Studio sea igual o mayor que la 1.5.1,
  • Versión de JDK mayor o igual que 7.
  • La versión de la aplicación (API Level)  tiene que ser mayor que Gingerbread, (versión 9, 2.3)

Primero, debemos configurar nuestro proyecto. Actualmente, Realm se instala como un plugin de gradle. Se configura en 2 pasos:

  1. Debemos añadir, en el build.gradle a nivel de proyecto, de donde recoger el plugin. Para ello necesitamos indicar el classpath de Realm, quedando este fichero de esta manera.
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0-alpha4'
        classpath "io.realm:realm-gradle-plugin:0.88.3"
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

2. Aplicaremos el plugin de Realm en tantos módulos del proyecto como necesitemos o queramos. Deberemos incluir apply plugin: ‘realm-android en los build.gradle de los módulos que queramos

apply plugin: 'com.android.application'
apply plugin: 'realm-android'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.asy.realmexample"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.2.1'
}

 

Inicializando Realm

Lo primero que debemos hacer para usar Realm, es configurar la base de datos. Podemos utilizar una configuración básica, pero desde mi punto de vista, esto no lo recomiendo, ya que es mejor preparar la base de datos tal y como la queramos. Podemos indicarle el nombre a nuestra base de datos, indicar la política de migración de datos, el version del esquema, encriptación y otras muchas mas configuraciones que se pueden añadir.

...

RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(application)
                .name("cars.realm")
                .deleteRealmIfMigrationNeeded()
                .schemaVersion(1)
                .build();

        Realm.setDefaultConfiguration(realmConfiguration);

...

 

Creando el modelo de datos

Para crear el modelo de datos en Realm, solo necesitaremos extender de la clase “RealmObject”. Deberemos asignarle una clave primaria con la anotación @PrimaryKey.

**
 * Database model for the entity CAR.
 *
 * @author asanchezyu@gmail.com.
 * @version 1.0.
 * @since 13/4/16.
 */
public class CarDb extends RealmObject {

    public static final String K_CAR_PLATE_NUMBER = "plateNumber";

    @PrimaryKey
    private String plateNumber;

    private Date registrationDate;

    private String model;

    private String brand;

    public CarDb() {
    }

    private CarDb(Builder builder) {

        this.registrationDate = builder.registrationDate;

        this.model = builder.model;

        this.plateNumber = builder.plateNumber;

        this.brand = builder.brand;

    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getPlateNumber() {
        return plateNumber;
    }

    public void setPlateNumber(String plateNumber) {
        this.plateNumber = plateNumber;
    }

    public Date getRegistrationDate() {
        return registrationDate;
    }

    public void setRegistrationDate(Date registrationDate) {
        this.registrationDate = registrationDate;
    }

    public static class Builder {

        private Date registrationDate;

        private String model;

        private String plateNumber;

        private String brand;

        public Builder setBrand(String brand) {
            this.brand = brand;
            return this;
        }

        public Builder setModel(String model) {
            this.model = model;
            return this;
        }

        public Builder setPlateNumber(String plateNumber) {
            this.plateNumber = plateNumber;
            return this;
        }

        public Builder setRegistrationDate(Date registrationDate) {
            this.registrationDate = registrationDate;
            return this;
        }

        public CarDb build() {
            return new CarDb(this);
        }
    }

}

 

Insertar datos.

Existen varias formas para realizar las inserciones de datos:

  • Creando la instancia por el constructor.
...

//Request realm instance
Realm realm = Realm.getDefaultInstance();

//Init the element
CarDb car = new CarDb();

car.setPlateNumber("1111-SSS");

car.setBrand("Citroen");

car.setModel("ZX");


//Insert element
realm.beginTransaction();

realm.copyToRealm(carDb);

realm.commitTransaction();

...
  • Obteniendo un objeto desde Realm.
...

//Request realm instance
Realm realm = Realm.getDefaultInstance();

//Begin transaction
realm.beginTransaction();

//Init the element
CarDb car = realm.createObject(CarDb.class);

car.setPlateNumber("1111-SSS");

car.setBrand("Citroen");

car.setModel("ZX");

//Commit transaction
realm.commitTransaction();

...

Realizar consultas de datos.

Se pueden realizar consultas de todo tipo: Filtrados por fechas, campos mayores,menores, o iguales que ciertos valores,..

...

Realm realm = Realm.getDefaultInstance();

RealmResults<CarDb> results = realm.where(CarDb.class)
                .equalTo(CarDb.K_CAR_PLATE_NUMBER, "1111-SSS")
                .or()
                .equalTo(CarDb.K_CAR_PLATE_NUMBER, "3333-XXX")
                .findAll();

...

Eliminar elementos.

Para suprimir objetos de nuestra base de datos, primero deberemos realizar una consulta de los objetos que queremos eliminar. A continuación, realizaremos el limpiado de los resultados.

...

Realm realm = Realm.getDefaultInstance();

realm.beginTransaction();

//Make the query.
RealmQuery<CarDb> realmQuery = realm.where(CarDb.class).equalTo(CarDb.K_CAR_PLATE_NUMBER, "1111-SSS");

RealmResults<CarDb> realmResults = realmQuery.findAll();

//Remove elements.
realmResults.clear();

//Commit changes.
realm.commitTransaction();

...

 

Problemas que me he encontrado usando Realm.

  1. Por ahora, no existe un campo autoincrementable, muy util para id’s de atributos autogenerados.
  2. No se puede extender de una clase que a su vez extienda de RealmObject.
  3. Al principio tuve problemas ejecutando las consultas en un hilo secundario. Esto se soluciona teniendo una clase que sea proveedora.

AQUI puedes ver un ejemplo de Realm, con MVP y arquitectura clean (basado en el ejemplo de Jorge Castillo).