Flutter - HiveDB

View Source Code Here

Hive DB

This example explores the use of HiveDB for local storage in dart & flutter

Dependencies

HiveDB requires four entries in your pubspec.yaml. Two belong under the standard dependencies section and another 2 are required in the dev section. These last two are used to generate the adapters from the command line

dependencies:
  flutter:
    sdk: flutter
  
  # hive database
  hive: ^2.0.3
  hive_flutter: ^1.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter

  # hive database
  build_runner: ^1.12.2
  hive_generator: ^1.0.1

Initialize HiveDB

In both flutter and Dart you need to initialize the database and register adapters.

In the dart example the entry looks like the following

example.dart

void main() async {
  Hive.init('./'); 

  // Register the Adapter
  Hive.registerAdapter(UserAdapter());
  // Open the box (Database) 
  var box = await Hive.openBox<User>('userBox');
  
}

in the flutter example it looks like this

main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize Hive
  await Hive.initFlutter();

  // Register the Adapter
  Hive.registerAdapter(QuoteAdapter());
  // Open the box (Database) 
  await Hive.openBox<Quote>('quotesdb');

  runApp(const MyApp());
}

TypeAdapter Generation

Hive requires a TypeAdapter to serialize the objects into binary formats. A tool is provided that will generate this Adapter for you. You included it in the pubspec.yaml earlier.

In order work correctly you need to annontate your object at the class and field levels. The system uses a simple numeric model to map the classes and fields so its critical that each class uses it’s own id and each field is also unique. Furthermore do not reuse one id on another field later. Instead just provide a new id for the new field.

Finnally the model should reference the generated TypeAdapter, in this case quoteModel.g.dart. This will produce an error until you actually generate the adapter and thats fine.

import 'package:hive/hive.dart';
part 'quoteModel.g.dart';

@HiveType(typeId: 0)
class Quote {
  @HiveField(0)
  late String? quoteid; 

  @HiveField(1)
  late String? text;

  @HiveField(2)
  late String? author;
}

To generate the adapter run flutter pub run build_runner build from the command line in the root of the project.

Reading and writing objects

Hive stores data in a simple Key:Value model. If no key is provided hive will simply use an auto incrementing index id for the key. It’s recommended that you provide your own key.

A simple example

example.dart

void main() async {
  Hive.init('./'); 
  Hive.registerAdapter(UserAdapter());

  var box = await Hive.openBox<User>('userBox');

  box.put('keydavid', User('David'));
  box.put('keysandy', User('Sandy'));

  print(box.keys);
}

Refreshing Views

To automatically update views anytime data is changed in the DB use ValueListenableBuilder to watch the data

quotePage.dart

Widget buildBody() {
    return ValueListenableBuilder<Box<Quote>>(
      valueListenable: Quote.quotesDB().listenable(),
      builder: (context, box, _) {
        final quotes = box.values.toList().cast<Quote>();

        return ListView.builder(
          itemCount: quotes.length,
          itemBuilder: (BuildContext context, int index) {
            return QuoteCard(quote: quotes[index]);
          },
        );
      },
    );
  }

Design Pattern in this example

This example implements a design pattern where the app generates a key rather than the DB. This pattern follows one I’ve used frequently with Firebase Firestore and should allow for consistent mental models and simplify translation between persistence tiers.

[[../../../_notes/_tech/Flutter/Flutter|Back to Flutter]]