Existen diferentes bases de datos para incorporar a una aplicación Flutter, cada una con sus ventajas y desventajas. En este artículo, junto a una pequeña introducción, vamos a ver específicamente una base de datos para trabajar en Flutter: Moor. Así que, adelante, ¡incluye la base de datos Moor en Flutter!

La introducción a Moor la haremos desarrollando un pequeño proyecto en Flutter, que puedes descargar de GitHub.

Base de datos Moor.

Introducción

Cuando empezamos a desarollar aplicaciones, llega un momento en que nos encontramos con la necesidad de guardar datos dentro de la propia aplicación: información sobre el usuario, datos generados…

En ese punto, lo que hacemos es introducir una base de datos en el desarrollo de la aplicación. Pero, ¿qué base de datos elegimos para trabajar?

Tipos de bases de datos

Hoy en día existen numerosas bases de datos que se pueden usar en el desarrollo móvil, pero se pueden clasificar, básicamente, en dos grupos: Relacionales y NoSQL

Bases de datos relacionales

En las bases de datos relacionales, la información se guarda en tablas (con filas y columnas, donde cada fila representa un registro y cada columna un atributo de ese registro). Además de los datos guardados, este tipo de base de datos también guarda las relaciones entre ellos.

Por ejemplo, SQLite es un ejemplo de base de datos relacional, que podemos implementar en Flutter mediante el paquete SQFLite.

Bases de datos NoSQL

Las bases de datos NoSQL no tienen esquemas predefinidos como los tendrían las bases de datos relacionales. Un claro ejemplo, son las bases de datos como MongoDB, que guardan la información en forma de documentos y que permiten trabajar fácilmente con información no estructurada.

¿Qué es Moor?

Moor es una librería para Flutter que nos permite trabajar con la base de datos SQLite de forma fácil y en Dart. Moor trabaja usando SQFLite y, lo que Moor hace por nosotros es transformar nuestro código Dart en lenguaje SQL (aunque también nos permite usar SQL).

¿Cómo instalar Moor en nuestro proyecto?

El primer paso para usar Moor en nuestros proyectos es instalar una serie de dependencias (actualizado). Primero creamos un proyecto introduciendo el siguiente comando en el terminal:

Después accedemos al fichero pubspec.yaml (por ejemplo, mediante Visual Studio Code) e incluimos las dependencias:

  • moor_flutter. Esta librería es el corazón de Moor.
  • moor_generator. Esta librería es la encargada de transformar las clases con las que creamos las tablas de la base de datos en lenguaje de bases de datos.
  • build_runner. Esta librería genera los archivos de la base de datos en lenguaje Dart.

Además añadimos la librería path_provider, que nos permitirá encontrar y añadir la base de datos a las sandbox de la aplicación, y la librería get_it, que es un proveedor de servicios y nos servirá para establecer la clase AppDatabase como singleton.

Nuestra primera tabla en Moor

Una de las ventajas de Moor es que a la hora de crear una tabla lo podemos hacer directamente en Dart, sin utilizar lenguaje SQL. Supongamos que queremos que nuestra base de datos contenga una tabla de usuario.

Al utilizar Moor, crearemos una clase (en el fichero users.dart), que podemos llamar Users, y que extenderá de la clase Table:

Al añadir la característica autoIncrement al parámetro id conseguimos dos cosas: la primera es que este parámetro aumente en 1 cada vez que añadamos un usuario; la segunda es que en ese momento, el parámetro id pasa a ser la primaryKey de la tabla.

Tal como se puede ver, la clase Users será nuestra tabla en la base de datos, mientras que las propiedades definidas como getters, serán las columnas de la tabla. Moor acepta los siguientes tipos de datos:

Dart typeMoor expression
intinteger()
doublereal()
booleanboolean()
Stringtext()
DateTimedateTime()
Uint8Listblob()

Creación de la base de datos

Ahora, lo que debemos hacer es crear la base de datos, y que esta tenga en cuenta la tabla Users. Eso lo hacemos con el siguiente código, que introduciremos en la clase database_manager.dart:

Este código contiene dos partes diferenciadas:

  • En la primera parte creamos el fichero db.sqlite que será el que guarde los datos en el sandbox de la aplicación (a partir del directorio de documentos que obtenemos mediante la instrucción getApplicationDocumentsDirectory()).
  • La segunda parte lo que hace es ejecutar la base de datos. Para ello, en nuestra aplicación simplemente deberemos hacer la llamada AppDatabase(openConnection()).

También hemos añadido la instrucción part ‘database_manager.g.dart’;, que contendrá el código generado.

Generación de código

Ahora simplemente hemos de hacer que se ejecute el proceso de generación de código (en el fichero database_manager.g.dart que hemos definido). Para ello vamos al terminal y ejecutamos el siguiente código:

Hora de añadir consultas

Una vez tenemos creada la base de datos con la tabla de usuarios, lo que nos falta es añadir las consultas que nos permitirán crear, actualizar, borrar… dichos usuarios.

Estas consultas se pueden añadir directamente en la clase AppDatabase que hemos creado anteriormente:

Ten en cuenta que en el caso de la actualización de un objeto de la tabla, este se hace usando la primaryKey de dicho objeto (en nuestro caso es el parámetro id, que se había marcado como primaryKey al añadirle la opción autoIncrement).

Es la hora de Flutter

Ahora que ya tenemos el proyecto creado y hemos incluido las clases database_manager.dart y users.dart, podemos continuar creando la interfaz de usuario que nos permitirá crear un usuario.

Adición del proveedor de servicios

Para poder establecer la clase AppDatabase como singleton, usaremos la librería get_it, que es un proveedor de servicios y que nos permitirá acceder a la base de datos desde cualquier punto de la aplicación.

Esto lo haremos creando la clase service_locator.dart, en la que introduciremos el siguiente código:

Lo que nos permite setupLocator() es inicializar la base de datos y registrarla como singleton.

Inicio de la aplicación

Para empezar, tomaremos la clase main.dart que se ha creador al generar el proyecto, borraremos todo su contenido y añadiremos el siguiente código:

Hemos modificado la llamada a main() para que sea asíncrona, ya que la llamada setupLocator() devuelve un Future: cuando acabe de ejecutarse esta llamada, se ejecutará el resto de la aplicación.

La pantalla de introducción de datos

Ahora crearemos una pantalla simple para introducir los datos con los que crearemos el usuario en la base de datos.

Para ello, creamos un fichero home.dart y añadimos el siguiente código:

Se trata de una StatefulWidget al que añadimos cuatro widgets CustomTexField y un widget RaisedButton.

El widget CustomTextField es un componente que creamos aparte para personalizar un widget de tipo TextField y, por otra parte, para reutilizar código. Con este motivo creamos el fichero custom_textfield.dart y añadimos el siguiente código:

Puesta en marcha de la aplicación

Con todo el código en su sitio, vamos a ejecutar el código en un simulador iOS Para ello, en primer lugar cargamos el simulador (a partir de la aplicación Simulator) y luego, en el terminal, desde el directorio raíz del proyecto ejecutamos:

Tras el proceso de ejecución, el simulador muestra la siguiente pantalla:

Pantalla del siumulador

Introducimos los diferentes datos:

Pantalla del simulador

Y presionamos el botón ‘Add User‘.

Se trata de una aplicación simple, en la que no hemos añadido ninguna otra pantalla para verificar los datos guardados. Pero para comprobar que todo ha ido bien, simplemente hemos de hacer una búsqueda del fichero db.sqlite en el directorio Biblioteca > Developer > CoreSimulator > Devices… (si se trata de macOSX).

Una vez encontrado el fichero podemos abrirlo con una aplicación como DB Browser for SQLite, y podremos ver cómo sí se han guardado los datos.

Comprobación del guardado de datos

Conclusiones

En este artículo he querido hacer una pequeña introducción al uso de bases de datos en proyectos desarrollados con Flutter y, en especial, al uso de la base de datos Moor. Esta base de datos tiene muchas más posibilidades que iremos viendo en artículos posteriores.


2 comentarios

mike · 2 julio 2021 a las 00:15

una pregunta si modelo user contiene adentro otro modelo? como se mapearia eso, saludos y gran tutorial.

    mike · 2 julio 2021 a las 00:16

    Es decir cuando creas la tabla, saludos

Deja una respuesta

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

Sígueme en Feedly