Hive: co to jest, magazyn NoSQL i programowanie bez kodu natywnego

Autor: IT Sectr Opublikowano: 2026-03-13 Czas czytania: 9 min

Hive — lekkie magazyn NoSQL dla Flutter, działający bez kodu natywnego. W przeciwieństwie do SQLite czy Firebase, Hive nie wymaga podłączania natywnych bibliotek i działa wyłącznie przez Dart. Według danych Pub.dev, 2024, Hive został pobrany ponad 10 milionów razy i jest używany w co trzecim projekcie Flutter, który wymaga lokalnego przechowywania danych bez infrastruktury serwerowej.

Najważniejsze

  • Hive — baza NoSQL w czystym Dart, bez kodu natywnego i zależności platformowych
  • Wydajność — do 30 000 odczytów na sekundę na urządzeniu mobilnym
  • Typowanie — TypeAdapter dla niestandardowych obiektów, bez generowania kodu
  • Levkość — 0 zależności od Android SDK lub iOS UIKit
  • Reaktywność — WatchBox do śledzenia zmian w czasie rzeczywistym

Czym jest Hive?

Hive — to baza danych NoSQL napisana w całości w Dart i niewymagająca natywnych bibliotek. Została stworzona przez Simona Leitera w 2019 roku jako alternatywa dla SQLite w projektach Flutter. Hive przechowuje dane w formacie binarnym .hive, który jest zoptymalizowany pod kątem szybkiego odczytu i zapisu na urządzeniach mobilnych. Format .hive używa niestandardowego schematu serializacji, w którym każdy typ danych ma swój bajtowy prefiks, co pozwala czytać plik bez wcześniejszej znajomości schematu — w przeciwieństwie do Protocol Buffers czy FlatBuffers.

Główna idea Hive — maksymalna prostota. Baza danych nie wymaga inicjalizacji natywnych silników, nie zawiera parsera SQL i nie używa refleksji. Wszystkie operacje to bezpośrednie wywołania funkcji Dart z binarną serializacją przez WriteBuffer i ReadBuffer.

Według ankiety Flutter Community (2023), Hive znajduje się w top 5 najczęściej używanych pakietów do przechowywania danych we Flutter, ustępując popularnością tylko shared_preferences, ale przewyższając go funkcjonalnością i szybkością.

Architektura Hive

Hive używa koncepcji Box — odpowiednika tabeli w relacyjnych bazach danych. Każdy Box to plik na dysku z zestawem par klucz-wartość. Kluczem może być int lub String, wartością — dowolny typ prymitywny, lista, Map lub niestandardowy obiekt przez TypeAdapter. Box-y są od siebie izolowane i otwierane niezależnie.

Zalety w porównaniu z rozwiązaniami natywnymi

Hive nie wymaga kanałów platformowych (platform channels). Oznacza to, że działa tak samo na Android, iOS, Web, macOS, Windows i Linux bez dodatkowej konfiguracji. Dla projektów ukierunkowanych na kompilację webową, Hive pozostaje jedynym lekkim rozwiązaniem NoSQL — SQLite w przeglądarce nie działa. Jednocześnie Hive używa IndexedDB jako backendu dla web, co zapewnia trwałość danych również w środowisku przeglądarkowym.

Jak działa Hive?

Hive serializuje dane do formatu binarnego przy zapisie i deserializuje przy odczycie. Wewnętrzny mechanizm opiera się na BinaryWriter i BinaryReader, które pakują dane w kompaktowe tablice bajtów. Rozmiar magazynu na dysku jest średnio 2–3 razy mniejszy niż reprezentacja JSON tych samych danych.

Przy otwieraniu Box Hive ładuje cały plik do pamięci RAM. Zapewnia to wysoką szybkość odczytu (mikrosekundy), ale nakłada ograniczenie na rozmiar danych: zaleca się przechowywanie w Hive nie więcej niż 50–100 MB na jeden Box. Dla większych ilości używaj LazyBox — leniwego ładowania rekordów z dysku.

Transakcje i współbieżność

Hive działa jednowątkowo w izolacji Dart-isolate. Operacje zapisu wykonywane są synchronicznie z blokadą pliku. Do asynchronicznego dostępu używaj Hive.openBox() z await. Współbieżny dostęp z wielu izolatów nie jest obsługiwany bezpośrednio — do tego potrzebny jest osobny mechanizm synchronizacji.

Hive vs SharedPreferences i vs SQLite

Hive zajmuje niszę między SharedPreferences a SQLite. Jest bardziej złożony niż SharedPreferences (obsługuje niestandardowe obiekty), ale prostszy niż SQLite (nie wymaga zapytań SQL). Porównajmy kluczowe cechy.

CechaHiveSharedPreferencesSQLite
Typy danychDowolne (przez TypeAdapter)Tylko prymitywyTypy SQL
Szybkość odczytu~30 000 ops/s~5 000 ops/s~2 000 ops/s
Kod natywnyNie wymaganyWymagany (Android)Wymagany
Web supportTakNieNie
ZłożonośćNiskaMinimalnaŚrednia
ReaktywnośćWatchBoxNiePrzez ORM

Kiedy wybrać Hive

Hive jest optymalny dla małych ilości danych: ustawień aplikacji, pamięci podręcznej odpowiedzi API, lokalnej kolejki synchronizacji, ulubionych i historii przeglądania. Jeśli dane nie przekraczają 50 MB i nie wymagają zapytań relacyjnych — Hive jest szybszy i prostszy niż SQLite.

Kiedy Hive nie pasuje

Hive nie obsługuje zapytań z filtrowaniem po wielu polach, JOIN, funkcji agregujących. Jeśli potrzebujesz złożonych zapytań typu “wybierz wszystkie zadania na dziś z priorytetem powyżej 3” — używaj SQLite z drift lub floor. Hive również nie nadaje się do przechowywania ponad 100 MB danych z powodu ładowania do pamięci.

Przykłady kodu z Hive

Hive zaczyna działanie od inicjalizacji i otwarcia Box. Poniżej przedstawiono podstawowe operacje dla typowego scenariusza — przechowywania listy zadań w aplikacji Flutter. Wszystkie przykłady działają bez natywnych wywołań platformowych.

Inicjalizacja i otwarcie Box

Przed użyciem Hive należy wywołać Hive.initFlutter() w funkcji main. Następnie otworzyć Box przez Hive.openBox() — wynikiem będzie instancja Box gotowa do odczytu i zapisu.

dart
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());
}

Operacje CRUD

Box udostępnia metody put, get, delete oraz zawiera iterator do przeglądania wszystkich rekordów. Klucze i wartości są typowane przez generyki — domyślnie Box<dynamic> dopuszcza dowolne typy, ale zaleca się określenie konkretnego typu.

dart
// Zapis danych
final box = await Hive.openBox<String>('tasks');
await box.put('task_1', 'Kup produkty');

// Odczyt
final task = box.get('task_1');

// Wszystkie klucze
final allTasks = box.values.toList();

// Usuwanie
await box.delete('task_1');

// Czyszczenie Box
await box.clear();

Reaktywne obserwowanie przez WatchBox

WatchBox — rozszerzenie Box, które powiadamia subskrybentów o zmianach. We Flutter integruje się to z ValueListenableBuilder: przy zmianie dowolnej wartości w Box widżet przebudowuje się automatycznie, bez wywoływania setState.

dart
final watchBox = await Hive.openBox('settings');

// W widżecie
ValueListenableBuilder(
    valueListenable: watchBox.listenable(),
    builder: (context, box, _) {
        final counter = box.get('counter') ?? 0;
        return Text('Licznik: $counter');
    },
)

TypeAdapter i niestandardowe obiekty

TypeAdapter — mechanizm Hive do serializacji niestandardowych obiektów Dart. Adapter opisuje, jak przekształcić obiekt do formatu binarnego (write) i z powrotem (read). W przeciwieństwie do json_serializable, TypeAdapter nie wymaga refleksji i działa szybciej.

Tworzenie TypeAdapter

Adapter implementuje interfejs TypeAdapter z dwiema metodami: read i write. Klasa rejestrowana jest przez Hive.registerAdapter() przed otwarciem Box. Każdemu adapterowi przypisywany jest numeryczny ID — zapisywany w pliku do identyfikacji typu.

dart
// Model danych
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);
    }
}

Generowanie adapterów przez kodogenerację

Dla projektów z dużą liczbą modeli Hive udostępnia hive_generator i build_runner. Adnotacja @HiveType na klasie i @HiveField na polach generuje adapter automatycznie. Jest to wygodne, gdy model zawiera 10+ pól — ręczne pisanie read/write staje się pracochłonne.

Optymalizacja wydajności Hive

Hive wykonuje odczyt z pamięci, a nie z dysku, co daje szybkość do 30 000 operacji na sekundę. Aby zoptymalizować: otwieraj Box raz i używaj go ponownie w całej aplikacji, nie wywołuj openBox ponownie. Używaj Hive.box() (synchroniczny getter) po inicjalizacji — zwraca już otwarty Box bez tworzenia nowej instancji.

Hive w połączeniu z Provider i Riverpod

Hive łatwo integruje się z popularnymi menedżerami stanu Flutter. Dla Provider używaj ChangeNotifierProvider, który czyta dane z Box przy inicjalizacji i aktualizuje się przez listenable. Dla Riverpod odpowiedni będzie StreamProvider subskrybujący WatchBox. Takie połączenie daje reaktywne aktualizacje UI przy każdej zmianie danych w Hive bez ręcznego wywoływania setState. W typowym projekcie Flutter taka architektura pozwala synchronizować stan między ekranami bez globalnego singletona.

Najczęściej zadawane pytania

Czy można używać Hive bez Flutter?

Hive działa w czystym Dart, więc można go używać w każdym projekcie Dart: serwerowym (Dart VM), konsolowym lub w AngularDart. Dla Flutter dodatkowo podłącza się hive_flutter z inicjalizacją ścieżek przechowywania.

Jak zaszyfrować dane w Hive?

Hive obsługuje szyfrowanie AES-256 przez parametr encryptionKey przy otwieraniu Box. Klucz musi być 32-bajtowym ciągiem. Zaszyfrowanego Box nie można odczytać bez klucza — dane są chronione na poziomie pliku.

Czym Hive różni się od Isar?

Isar — następca Hive od tego samego autora (Simon Leiter). Isar jest szybszy, obsługuje indeksy, relacje i złożone zapytania. Jednak Hive pozostaje aktualny dla prostych scenariuszy, gdzie nie są potrzebne relacyjne możliwości Isar, oraz dla projektów, w których ważna jest minimalna liczba zależności.

Czy Hive obsługuje migracje schematu?

Hive nie ma wbudowanych migracji. Jeśli struktura TypeAdapter się zmieniła, stare dane nie będą deserializowane. Rozwiązanie: zwiększ typeId adaptera i napisz ręczną migrację w kodzie albo użyj delete dla starego klucza przed zapisem nowego.

Jaki jest maksymalny rozmiar Hive Box?

Hive ładuje Box do pamięci w całości. Zalecany limit to 50–100 MB na jeden Box. Po przekroczeniu możliwe są opóźnienia przy otwieraniu Box i zwiększone zużycie RAM. Dla większych ilości używaj kilku Box-ów lub LazyBox z leniwym ładowaniem.

Podsumowanie

  • Hive — baza NoSQL w czystym Dart, bez kodu natywnego i zależności platformowych
  • Wydajność — do 30 000 operacji odczytu na sekundę na urządzeniach mobilnych
  • TypeAdapter — binarna serializacja niestandardowych obiektów bez refleksji
  • WatchBox — reaktywne śledzenie zmian do automatycznej aktualizacji UI
  • Wieloplatformowość — Android, iOS, Web, macOS, Windows, Linux od ręki
  • Szyfrowanie — ochrona danych AES-256 na poziomie pliku Box
  • Zalecenie — używaj Hive do pamięci podręcznej, ustawień i małych ilości danych w projektach Flutter i Dart

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również