Hive es un almacenamiento NoSQL ligero para Flutter que funciona sin código nativo. A diferencia de SQLite o Firebase, Hive no requiere bibliotecas nativas y funciona exclusivamente a través de Dart. Según Pub.dev, 2024, Hive se ha descargado más de 10 millones de veces y se utiliza en uno de cada tres proyectos Flutter que necesitan almacenamiento local sin infraestructura de servidor.
Puntos clave
Hive es una base de datos NoSQL escrita completamente en Dart que no requiere bibliotecas nativas. Fue creada por Simon Leiter en 2019 como alternativa a SQLite para proyectos Flutter. Hive almacena datos en formato binario .hive optimizado para lectura y escritura rápidas en dispositivos móviles. El formato .hive utiliza un esquema de serialización personalizado donde cada tipo de dato tiene su propio prefijo de byte, permitiendo leer el archivo sin conocimiento previo del esquema — a diferencia de Protocol Buffers o FlatBuffers.
La idea principal de Hive es la máxima simplicidad. La base de datos no requiere inicialización de motores nativos, no incluye analizador SQL ni usa reflexión. Todas las operaciones son llamadas directas a funciones Dart con serialización binaria a través de WriteBuffer y ReadBuffer.
Según la encuesta de Flutter Community (2023), Hive está entre los 5 paquetes de almacenamiento de datos más usados en Flutter, solo superado por shared_preferences en popularidad, pero superándolo en funcionalidad y velocidad.
Hive utiliza el concepto de Box — análogo a una tabla en bases de datos relacionales. Cada Box es un archivo en disco con un conjunto de pares clave-valor. La clave puede ser int o String, el valor puede ser cualquier tipo primitivo, lista, Map o un objeto personalizado mediante TypeAdapter. Los Box están aislados entre sí y se abren de forma independiente.
Hive no requiere canales de plataforma. Esto significa que funciona igual en Android, iOS, Web, macOS, Windows y Linux sin configuración adicional. Para proyectos orientados a compilación web, Hive sigue siendo la única solución NoSQL ligera — SQLite no funciona en navegadores. Hive utiliza IndexedDB como backend para web, garantizando la persistencia de datos incluso en entornos de navegador.
Hive serializa datos en formato binario al escribir y deserializa al leer. El mecanismo interno se basa en BinaryWriter y BinaryReader, que empaquetan los datos en arrays de bytes compactos. El tamaño de almacenamiento en disco es en promedio 2–3 veces menor que la representación JSON de los mismos datos.
Al abrir un Box, Hive carga todo el archivo en RAM. Esto proporciona alta velocidad de lectura (microsegundos) pero impone una limitación de tamaño: se recomienda almacenar no más de 50–100 MB por Box. Para volúmenes mayores, use LazyBox — carga diferida de registros desde el disco.
Hive funciona en un solo hilo dentro de un aislado Dart. Las operaciones de escritura se realizan de forma síncrona con bloqueo de archivo. Para acceso asíncrono, use Hive.openBox() con await. El acceso concurrente desde múltiples aislados no es compatible directamente — se requiere un mecanismo de sincronización independiente.
Hive ocupa un nicho entre SharedPreferences y SQLite. Es más complejo que SharedPreferences (soporta objetos personalizados) pero más simple que SQLite (no requiere consultas SQL). Comparemos las características clave.
| Característica | Hive | SharedPreferences | SQLite |
|---|---|---|---|
| Tipos de datos | Cualquiera (mediante TypeAdapter) | Solo primitivos | Tipos SQL |
| Velocidad de lectura | ~30 000 ops/s | ~5 000 ops/s | ~2 000 ops/s |
| Código nativo | No requerido | Requerido (Android) | Requerido |
| Soporte web | Sí | No | No |
| Complejidad | Baja | Mínima | Media |
| Reactividad | WatchBox | No | Mediante ORM |
Hive es óptimo para volúmenes pequeños de datos: configuraciones de aplicación, caché de respuestas API, cola de sincronización local, favoritos e historial de navegación. Si los datos no superan los 50 MB y no requieren consultas relacionales — Hive es más rápido y simple que SQLite.
Hive no soporta consultas con filtrado por múltiples campos, JOIN ni funciones agregadas. Si necesita consultas complejas como “seleccionar todas las tareas de hoy con prioridad superior a 3” — use SQLite con drift o floor. Hive tampoco es adecuado para almacenar más de 100 MB de datos debido a la carga en memoria.
Hive comienza con la inicialización y apertura de un Box. A continuación se presentan las operaciones básicas para un escenario típico — almacenar una lista de tareas en una aplicación Flutter. Todos los ejemplos funcionan sin llamadas nativas de plataforma.
Antes de usar Hive, debe llamar a Hive.initFlutter() en la función main. Luego abra un Box mediante Hive.openBox() — el resultado será una instancia de Box lista para lectura y escritura.
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
void async main() {
await Hive.initFlutter();
final settingsBox = await Hive.openBox('settings');
runApp(MyApp());
}
Box proporciona los métodos put, get, delete y un iterador para recorrer todas las entradas. Las claves y valores se tipifican mediante genéricos — por defecto Box<dynamic> acepta cualquier tipo, pero se recomienda especificar un tipo concreto.
// Escribir datos
final box = await Hive.openBox<String>('tasks');
await box.put('task_1', 'Comprar alimentos');
// Lectura
final task = box.get('task_1');
// Todas las claves
final allTasks = box.values.toList();
// Eliminar
await box.delete('task_1');
// Limpiar Box
await box.clear();
WatchBox es una extensión de Box que notifica a los suscriptores sobre cambios. En Flutter, esto se integra con ValueListenableBuilder: cuando cualquier valor en el Box cambia, el widget se reconstruye automáticamente sin llamar a setState.
final watchBox = await Hive.openBox('settings');
// En el widget
ValueListenableBuilder(
valueListenable: watchBox.listenable(),
builder: (context, box, _) {
final counter = box.get('counter') ?? 0;
return Text('Contador: $counter');
},
)
TypeAdapter es el mecanismo de Hive para serializar objetos Dart personalizados. El adaptador describe cómo convertir un objeto a formato binario (write) y viceversa (read). A diferencia de json_serializable, TypeAdapter no requiere reflexión y es más rápido.
El adaptador implementa la interfaz TypeAdapter
// Modelo de datos
class Task {
final String title;
final bool isCompleted;
Task({required this.title, this.isCompleted = false});
}
// TypeAdapter
class TaskAdapter extends TypeAdapter<Task> {
@override
final int typeId = 0;
@override
Task read(BinaryReader reader) {
return Task(
title: reader.readString(),
isCompleted: reader.readBool(),
);
}
@override
void write(BinaryWriter writer, Task obj) {
writer.writeString(obj.title);
writer.writeBool(obj.isCompleted);
}
}
Para proyectos con un gran número de modelos, Hive proporciona hive_generator y build_runner. La anotación @HiveType en la clase y @HiveField en los campos generan el adaptador automáticamente. Esto es conveniente cuando el modelo tiene 10+ campos — la escritura manual de read/write se vuelve tediosa.
Hive lee desde la memoria en lugar del disco, proporcionando velocidades de hasta 30 000 operaciones por segundo. Para optimizar: abra un Box una vez y reutilícelo en toda la aplicación, no llame a openBox repetidamente. Use Hive.box() (getter síncrono) después de la inicialización — devuelve un Box ya abierto sin crear una nueva instancia.
Hive se integra fácilmente con los gestores de estado populares de Flutter. Para Provider, use ChangeNotifierProvider que lee datos del Box al inicializar y se actualiza mediante listenable. Para Riverpod, un StreamProvider suscrito a WatchBox funciona bien. Esta combinación proporciona actualizaciones reactivas de la interfaz en cada cambio de datos en Hive sin llamadas manuales a setState. En un proyecto Flutter típico, esta arquitectura permite sincronizar el estado entre pantallas sin un singleton global.
Preguntas frecuentes
Hive funciona en Dart puro, por lo que se puede usar en cualquier proyecto Dart: servidor (Dart VM), consola o AngularDart. Para Flutter, se requiere adicionalmente hive_flutter para la inicialización de rutas de almacenamiento.
Hive soporta cifrado AES-256 mediante el parámetro encryptionKey al abrir un Box. La clave debe ser una cadena de 32 bytes. Un Box cifrado no se puede leer sin la clave — los datos están protegidos a nivel de archivo.
Isar es el sucesor de Hive del mismo autor (Simon Leiter). Isar es más rápido, soporta índices, relaciones y consultas complejas. Sin embargo, Hive sigue siendo relevante para escenarios simples donde no se necesitan las capacidades relacionales de Isar, y para proyectos donde es importante tener dependencias mínimas.
Hive no tiene migraciones incorporadas. Si la estructura del TypeAdapter cambia, los datos antiguos no se deserializarán. Solución: aumente el typeId del adaptador y escriba una migración manual en código, o use delete para la clave antigua antes de escribir una nueva.
Hive carga el Box completamente en memoria. El límite recomendado es de 50–100 MB por Box. Superar esto puede causar retrasos al abrir el Box y un mayor consumo de RAM. Para volúmenes más grandes, use varios Box o LazyBox con carga diferida.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también