Persistencia de datos en Flutter: Sqflite, Floor, Hive e Isar.
AVISO ¡NO ES UN CURSO PARA INICIADOS! ¡SOLO PARA AQUELLOS CON CIERTA EXPERIENCIA!
El almacenamiento local de información en dispositivos móviles es esencial para el ahorro de datos y batería. Además es la base que permite la implementación de estrategias offline-first, es decir, aplicaciones donde todas o alguna de sus partes funcionen sin necesidad de internet. Esto conlleva a la obligación de sincronizar la información con el servidor siempre que exista la posibilidad, esto es, siempre que haya conexión a internet. Y adivina, para esta sincronización se requiere que los datos permanezcan en algún lugar, persistan, en el dispositivo móvil. Por tanto, los sistemas de almacenamiento local son esenciales en el desarrollo de aplicaciones móviles.
Teniendo todo lo anterior en cuenta, las aplicaciones desarrolladas mediante Flutter no son menos que las desarrolladas con Kotlin y Swift. También se debe implementar persistencia local cuando sea necesario. Para ello, Flutter cuenta con muchas bibliotecas que solucionan el problema de una forma sencilla y eficaz. Podemos encontrar soluciones tanto SQL como NoSQL, y es por ello que es necesario conocerlas, ya que nos pueden salvar en muchas situaciones. En el presente curso se tratarán cuatro bibliotecas diferentes: dos de tipo SQL y otras dos NoSQL.
En resumen, durante este curso crearemos la capa de datos de la aplicación. Dejando el código preparado para comenzar a implementar cualquier tipo de base de datos: sqflite, floor, Hive o Isar. El curso ha sido pensado para que, una vez terminado el módulo común, podáis comenzar por cualquier sistema de almacenamiento mencionado antes. Para las partes comunes tendréis el código disponible para descargar desde mi cuenta de GitHub.
Secciones del curso
1. Introducción a Flutter Riverpod
Empezaremos directamente por un recordatorio/guía básica de flutter_riverpod, una librería que se utiliza para manejar el estado y también como inyección de dependencias. Realmente, utilizaremos el StateNotifierProvider para inyectar nuestro ViewModel en los widgets donde se vaya a observar algún estado o lanzar alguna funcionalidad que haga que este cambie.
2. Introducción a la App de Ejemplo
Explicación la aplicación que os he proporcionado (completamente funcional). Comentaré cosas como la estructura de carpetas, como funciona cada pantalla, etc. Desde aquí comenzará la siguiente sección, deshaciendo el desaguisado que existe en el viewmodel y creando desde cero la capa de datos.
3. Creación de la capa de datos
El objetivo de este módulo es hacer una refactorización del código para crear la capa de datos. Crearemos los DTO (Data Transfer Object), es decir, los modelos para la comunicación con la REST API y mapear los datos que esta nos envía. También crearemos las entidades a modo de preparación para implementar una base de datos, y que utilizaremos para `pintar` la información en nuestros Widgets.
Por tanto, realizaremos peticiones HTTP y crearemos el repositorio de Pokemon, donde implementaremos diferentes estrategias interesantes, como el hecho de utilizar Isolates para reducir la carga del proceso principal (y por tanto aumentar la eficiencia) cuando tenemos que hacer muchas peticiones al servidor. Combinaremos la estrategia de los isolates con funciones generadoras a través de los Stream para emitir el resultado de las peticiones HTTP desde el Isolate secundario al Isolate principal. Y por último, también implementaremos un sistema de caché en memoria para los tipos y los movimientos, los cuales nos ayudarán muchísimo a la hora de ´pintar´ la información en nuestra pantalla de forma eficiente.
4. Persistencia con Hive
Implementaremos Hive como sistema de almacenamiento local para aumentar la eficiencia de la carga de datos una vez que hayamos guardado la información.
5. Persistencia con Isar
Implementaramos Isar, que se puede decir que es la evolución de Hive, y aprenderemos a utilizar las anotaciones necesarias para su correcto funcionamiento. También aprenderemos a utilizar su fabuloso inspector, además de otras cosas importantes como los índices y el build runner.
6. Persistencia con Sqflite
Crearemos una base de datos SQLite de forma completamente manual, escribiendo las queries a mano. Esto nos permite comprobar la diferencia que existe con Hive e Isar. A priori, Hive e Isar son mucho más sencillos tanto de implementar como de manejar. Sin embargo, las bases de datos de tipo relacional nos permiten tener una integridad de datos que no se puede alcanzar con las NoSQL. Ambas tienen sus ventajas e inconvenientes.
Algunas cosas que veremos en este módulo son: almacenamiento y queries de datos, transacciones y migraciones.
7. Persistencia con Floor
Floor nos permite implementar una base de datos de tipo SQLite, al igual que sqflite. No obstante, la principal diferencia con respecto a esta es que podemos automatizar la creación de tablas y sus relaciones a través de las anotaciones que hagamos en el código. Esto, junto con la creación de los Dao, nos permite automatizar con el build_runner toda la generación de código necesaria para persistir datos.
Aprenderemos, por tanto, a crear todas las entidades para la creación de la base de datos, además de utilizar el código generado por el build runner para persistir información. Aprenderemos a crear queries propias e incluso la flexibilidad que nos da Floor al permitirnos utilizar queries nativas para obtener la información que queramos y mapear al modelo/s que queramos. El último tema que trataremos es el de las migraciones.