Hive — un depozit NoSQL ușor pentru Flutter, care funcționează fără cod nativ. Spre deosebire de SQLite sau Firebase, Hive nu necesită conectarea bibliotecilor native și funcționează exclusiv prin Dart. Conform Pub.dev, 2024, Hive este descărcat de peste 10 milioane de ori și este utilizat în fiecare al treilea proiect Flutter care necesită stocare locală de date fără infrastructură de server.
Principalele puncte
Hive — este o bază de date NoSQL scrisă în întregime în Dart, care nu necesită biblioteci native. A fost creată de Simon Leiter în 2019 ca alternativă la SQLite pentru proiecte Flutter. Hive stochează datele în format binar .hive, optimizat pentru citire și scriere rapidă pe dispozitive mobile. Formatul .hive utilizează un schema de serializare personalizată, în care fiecare tip de date are propriul prefix de octet, permițând citirea fișierului fără cunoașterea prealabilă a schemei — spre deosebire de Protocol Buffers sau FlatBuffers.
Ideea principală a Hive — simplitate maximă. Baza de date nu necesită inițializarea motoarelor native, nu include un parser SQL și nu utilizează reflecție. Toate operațiile sunt apeluri directe ale funcțiilor Dart cu serializare binară prin WriteBuffer și ReadBuffer.
Conform sondajului Flutter Community (2023), Hive se află în top 5 cele mai utilizate pachete pentru stocarea datelor în Flutter, fiind secondat doar de shared_preferences în popularitate, dar depășindu-l în funcționalitate și viteză.
Hive utilizează conceptul de Box — analogul unui tabel în bazele de date relaționale. Fiecare Box este un fișier pe disc cu un set de perechi cheie-valoare. Cheia poate fi int sau String, valoarea — orice tip primitiv, listă, Map sau obiect personalizat prin TypeAdapter. Box-urile sunt izolate unele de altele și se deschid independent.
Hive nu necesită canale de platformă (platform channels). Aceasta înseamnă că funcționează la fel pe Android, iOS, Web, macOS, Windows și Linux fără configurare suplimentară. Pentru proiecte orientate spre compilarea web, Hive rămâne singura soluție ușoară NoSQL — SQLite nu funcționează în browser. În același timp, Hive utilizează IndexedDB ca backend pentru web, asigurând persistența datelor și în mediul browser.
Hive serializează datele în format binar la scriere și deserializează la citire. Mecanismul intern se bazează pe BinaryWriter și BinaryReader, care împachetează datele în tablouri compacte de octeți. Dimensiunea depozitului pe disc este în medie de 2–3 ori mai mică decât reprezentarea JSON a acelorași date.
La deschiderea unui Box, Hive încarcă întregul fișier în memoria RAM. Aceasta asigură o viteză mare de citire (microsecunde), dar impune o limitare a dimensiunii datelor: se recomandă stocarea a cel mult 50–100 MB per Box. Pentru volume mai mari, utilizați LazyBox — încărcarea lazy a înregistrărilor de pe disc.
Hive funcționează monofirește în izolarea Dart-isolate. Operațiile de scriere se execută sincron cu blocarea fișierului. Pentru acces asincron, utilizați Hive.openBox() cu await. Accesul concurent din mai multe izolate nu este suportat direct — pentru aceasta este nevoie de un mecanism separat de sincronizare.
Hive ocupă o nișă între SharedPreferences și SQLite. Este mai complex decât SharedPreferences (suportă obiecte personalizate), dar mai simplu decât SQLite (nu necesită interogări SQL). Să comparăm caracteristicile cheie.
| Caracteristică | Hive | SharedPreferences | SQLite |
|---|---|---|---|
| Tipuri de date | Oricare (prin TypeAdapter) | Doar primitive | Tipuri SQL |
| Viteza de citire | ~30 000 ops/s | ~5 000 ops/s | ~2 000 ops/s |
| Cod nativ | Nu este necesar | Necesar (Android) | Necesar |
| Suport web | Da | Nu | Nu |
| Complexitate | Scăzută | Minimă | Medie |
| Reactivitate | WatchBox | Nu | Prin ORM |
Hive este optim pentru volume mici de date: setări aplicație, cache de răspunsuri API, coadă locală de sincronizare, favorite și istoric de vizualizare. Dacă datele nu depășesc 50 MB și nu necesită interogări relaționale — Hive este mai rapid și mai simplu decât SQLite.
Hive nu suportă interogări cu filtrare pe mai multe câmpuri, JOIN, funcții agregate. Dacă aveți nevoie de interogări complexe de tipul “selectează toate sarcinile de astăzi cu prioritate mai mare de 3” — utilizați SQLite cu drift sau floor. Hive nu este potrivit nici pentru stocarea a peste 100 MB de date din cauza încărcării în memorie.
Hive începe cu inițializarea și deschiderea unui Box. Mai jos sunt prezentate operațiile de bază pentru un scenariu tipic — stocarea unei liste de sarcini într-o aplicație Flutter. Toate exemplele funcționează fără apeluri native de platformă.
Înainte de a utiliza Hive, trebuie apelat Hive.initFlutter() în funcția main. Apoi deschideți Box prin Hive.openBox() — rezultatul va fi o instanță Box gata de citire și scriere.
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 oferă metodele put, get, delete și conține un iterator pentru parcurgerea tuturor înregistrărilor. Cheile și valorile sunt tipizate prin generice — în mod implicit Box<dynamic> acceptă orice tipuri, dar se recomandă specificarea unui tip concret.
// Scriere date
final box = await Hive.openBox<String>('tasks');
await box.put('task_1', 'Cumpără produse');
// Citire
final task = box.get('task_1');
// Toate cheile
final allTasks = box.values.toList();
// Ștergere
await box.delete('task_1');
// Curățare Box
await box.clear();
WatchBox — o extensie a Box care notifică abonații despre modificări. În Flutter, aceasta se integrează cu ValueListenableBuilder: la modificarea oricărei valori în Box, widget-ul se reconstruiește automat, fără a apela setState.
final watchBox = await Hive.openBox('settings');
// În widget
ValueListenableBuilder(
valueListenable: watchBox.listenable(),
builder: (context, box, _) {
final counter = box.get('counter') ?? 0;
return Text('Contor: $counter');
},
)
TypeAdapter — mecanismul Hive pentru serializarea obiectelor Dart personalizate. Adaptorul descrie cum se transformă un obiect în format binar (write) și înapoi (read). Spre deosebire de json_serializable, TypeAdapter nu necesită reflecție și funcționează mai rapid.
Adaptorul implementează interfața TypeAdapter
// Model de date
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);
}
}
Pentru proiecte cu un număr mare de modele, Hive oferă hive_generator și build_runner. Adnotarea @HiveType pe clasă și @HiveField pe câmpuri generează adaptorul automat. Acest lucru este convenabil când modelul conține 10+ câmpuri — scrierea manuală a read/write devine laborioasă.
Hive execută citirea din memorie, nu de pe disc, ceea ce oferă o viteză de până la 30 000 de operații pe secundă. Pentru optimizare: deschideți Box o singură dată și reutilizați-l în întreaga aplicație, nu apelați openBox din nou. Folosiți Hive.box() (getter sincron) după inițializare — returnează un Box deja deschis fără a crea o nouă instanță.
Hive se integrează ușor cu managerii de stare populari Flutter. Pentru Provider, utilizați ChangeNotifierProvider care citește datele din Box la inițializare și se actualizează prin listenable. Pentru Riverpod, este potrivit StreamProvider abonat la WatchBox. O astfel de combinație oferă actualizare reactivă a UI la fiecare modificare a datelor în Hive fără apelarea manuală a setState. Într-un proiect Flutter tipic, o astfel de arhitectură permite sincronizarea stării între ecrane fără un singleton global.
Întrebări frecvente
Hive funcționează în Dart pur, deci poate fi utilizat în orice proiect Dart: server (Dart VM), consolă sau AngularDart. Pentru Flutter, se conectează suplimentar hive_flutter cu inițializarea căilor de stocare.
Hive suportă criptarea AES-256 prin parametrul encryptionKey la deschiderea Box. Cheia trebuie să fie un șir de 32 de octeți. Box-ul criptat nu poate fi citit fără cheie — datele sunt protejate la nivel de fișier.
Isar — succesorul Hive de la același autor (Simon Leiter). Isar este mai rapid, suportă indecși, relații și interogări complexe. Cu toate acestea, Hive rămâne relevant pentru scenarii simple unde nu sunt necesare capacitățile relaționale ale Isar și pentru proiecte în care dependența minimă este importantă.
Hive nu are migrări încorporate. Dacă structura TypeAdapter s-a modificat, datele vechi nu se vor deserializa. Soluție: măriți typeId al adaptorului și scrieți o migrare manuală în cod sau utilizați delete pentru cheia veche înainte de a scrie una nouă.
Hive încarcă Box-ul în memorie integral. Limita recomandată este de 50–100 MB per Box. La depășire, pot apărea întârzieri la deschiderea Box și consum crescut de RAM. Pentru volume mai mari, utilizați mai multe Box-uri sau LazyBox cu încărcare lazy.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și