Datum Logo

Datum Hive

A Hive-based persistence layer for the Datum ecosystem, enabling efficient local data storage and synchronization for Flutter applications.

Features

  • Seamless integration with Datum for local data persistence.
  • Leverages Hive's high performance and ease of use.
  • Supports offline-first capabilities for Datum entities.
  • Provides robust and reliable data storage.

Getting started

Prerequisites

Ensure you have the datum package integrated into your Flutter project.

Installation

Add datum_hive to your pubspec.yaml file:

dependencies:
  datum_hive: ^latest_version

Then, run flutter pub get.

Usage

To integrate datum_hive with your Datum setup, you'll typically initialize Datum with IsolatedHiveLocalAdapter or HiveLocalAdapter for your entities.

First, define your Datum entity and a fromMap factory:

import 'package:datum/datum.dart';
import 'package:datum_hive/datum_hive.dart'; // For DatumHiveEntity
import 'package:hive_flutter/hive_flutter.dart'; // For Hive.initFlutter()

// Example Task entity
class Task extends DatumHiveEntity {
  Task(super.id, super.collection, {required this.title, required this.isComplete});

  final String title;
  final bool isComplete;

  factory Task.fromMap(Map<String, dynamic> map) {
    return Task(
      map['id'] as String,
      map['collection'] as String,
      title: map['title'] as String,
      isComplete: map['isComplete'] as bool,
    );
  }

  @override
  Map<String, dynamic> toMap() {
    return {
      ...super.toMap(), // Include base DatumHiveEntity fields
      'title': title,
      'isComplete': isComplete,
    };
  }
}

Then, initialize Hive and Datum based on your needs.

Using HiveLocalAdapter

If you don't need to run Hive in a separate isolate, you can use HiveLocalAdapter.

import 'package:datum/datum.dart';
import 'package:datum_hive/datum_hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:your_app/models/task.dart'; // Assuming Task is defined here
import 'package:your_app/services/connectivity_checker.dart'; // CustomConnectivityChecker
import 'package:your_app/services/datum_logger.dart'; // CustomDatumLogger
import 'package:your_app/observers/my_datum_observer.dart'; // MyDatumObserver
import 'package:your_app/remote_adapters/supabase_remote_adapter.dart'; // SupabaseRemoteAdapter

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized(); // Required for Flutter apps
  await Hive.initFlutter(); // Initialize Hive for the main isolate

  // Example Datum configuration
  final config = DatumConfig(
    appName: 'MyAwesomeApp',
    // ... other configurations
  );

  final datum = await Datum.initialize(
    config: config,
    connectivityChecker: CustomConnectivityChecker(),
    logger: CustomDatumLogger(enabled: config.enableLogging),
    observers: [
      MyDatumObserver(),
    ],
    registrations: [
      DatumRegistration<Task>(
        localAdapter: HiveLocalAdapter<Task>(
          entityBoxName: "tasks",
          fromMap: (map) => Task.fromMap(map),
          schemaVersion: 0,
        ),
        remoteAdapter: SupabaseRemoteAdapter(
          tableName: 'tasks',
          fromMap: Task.fromMap,
        ),
      ),
      // Add more DatumRegistrations for other entities
    ],
  );

  // Now you can use Datum to interact with your data
  final task = Task('123', 'tasks', title: 'Buy groceries', isComplete: false);
  await datum.save(task);
  final fetchedTask = await datum.get<Task>('123', 'tasks');
  print(fetchedTask?.title);
}

Using IsolatedHiveLocalAdapter

For better performance in Flutter, especially with large datasets, you can use IsolatedHiveLocalAdapter to run Hive in a separate isolate.

import 'package:datum/datum.dart';
import 'package:datum_hive/datum_hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:your_app/models/task.dart'; // Assuming Task is defined here
import 'package:your_app/services/connectivity_checker.dart'; // CustomConnectivityChecker
import 'package:your_app/services/datum_logger.dart'; // CustomDatumLogger
import 'package:your_app/observers/my_datum_observer.dart'; // MyDatumObserver
import 'package:your_app/remote_adapters/supabase_remote_adapter.dart'; // SupabaseRemoteAdapter

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized(); // Required for Flutter apps
  await IsolatedHive.initFlutter(); // Initialize Hive for a separate isolate

  // Example Datum configuration
  final config = DatumConfig(
    appName: 'MyAwesomeApp',
    // ... other configurations
  );

  final datum = await Datum.initialize(
    config: config,
    connectivityChecker: CustomConnectivityChecker(),
    logger: CustomDatumLogger(enabled: config.enableLogging),
    observers: [
      MyDatumObserver(),
    ],
    registrations: [
      DatumRegistration<Task>(
        localAdapter: IsolatedHiveLocalAdapter<Task>(
          entityBoxName: "tasks", // Unique name for your Hive box
          fromMap: (map) => Task.fromMap(map),
          schemaVersion: 0, // Increment this when your entity schema changes
        ),
        remoteAdapter: SupabaseRemoteAdapter(
          tableName: 'tasks',
          fromMap: Task.fromMap,
        ),
      ),
      // Add more DatumRegistrations for other entities
    ],
  );

  // Now you can use Datum to interact with your data
  final task = Task('123', 'tasks', title: 'Buy groceries', isComplete: false);
  await datum.save(task);
  final fetchedTask = await datum.get<Task>('123', 'tasks');
  print(fetchedTask?.title);
}

Isolates and IsolatedHive

Hive CE supports concurrent access across multiple isolates through the IsolatedHive interface.

The problem

The normal Hive interface is not safe to use across multiple isolates. Concurrent writes are almost guaranteed to corrupt box data.

Hive CE will print a warning in most cases when attempting to use Hive across multiple isolates.

Examples of multi-isolate usage

You may be using multiple isolates without even realizing it. Here are some common use-cases that result in code running in multiple isolates:

  • A Flutter desktop app with multiple windows
  • Running background tasks with flutter_workmanager, background_fetch, etc.
  • Push notification processing

Additional information

For more information on Datum, visit the Datum documentation. To contribute or report issues, please visit the GitHub repository. For issue tracking, please visit GitHub issues.

Libraries

datum_hive