Watch the video (22 min)
On this page14 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. The Model Class
  5. 2. Generate the Adapter
  6. 3. Rules That Protect Saved Data
  7. 4. Register the Adapter
  8. Code Examples
  9. Common Beginner Mistakes
  10. Best Practices
  11. Mini Challenge
  12. Practice Questions
  13. Practice Answers
  14. Key Takeaways

Lecture 003 — The Model Class & Type Adapter

Category2 — Models & Manager
Lecture003 of 007
Estimated video length22 min
TargetFlutter 3.44 · Dart 3.12 · hive 2.2
LevelBeginner
VideoPart 1 — Introduction, Setup, Model Adapters & Manager Classes
Source codeGitHub — urraan_hive_final_code

A box can hold text and numbers, but our contacts have a name, an address, a photo and hobbies. We describe that as a Dart class, then let Hive's generator write the code that turns it into bytes — the type adapter.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways


Prerequisites

Lectures 001–002 and Dart classes with fields and List<String>.


Connection With Previous Lectures

Lecture 002 stored a String. Hive knows how to save String, int, bool, List, Map and Uint8List. It does not know your DataObjects class — so we must teach it.


Learning Objectives

  • Annotate a class with @HiveType and fields with @HiveField
  • Run build_runner to generate the adapter
  • Choose typeId and field numbers, and know why they must never change
  • Give fields defaultValues so old records still load

1. The Model Class

dart
// lib/data_hive/data_objects.dart
import 'dart:typed_data';

import 'package:hive/hive.dart';

part 'data_objects.g.dart';

@HiveType(typeId: 0)
class DataObjects {
  @HiveField(0)
  dynamic key;

  @HiveField(1, defaultValue: '')
  String name = '';

  @HiveField(2, defaultValue: '')
  String address = '';

  @HiveField(3)
  Uint8List? profileImage;

  @HiveField(4, defaultValue: [])
  List<String> hobbies = [];
}

Line by line:

  • part 'data_objects.g.dart'; — the generated file becomes part of this one.
  • @HiveType(typeId: 0) — a unique id for this class across the whole app (0–223).
  • @HiveField(n) — the field's permanent number. Hive saves numbers, not names.
  • key — we store the record's own key inside the object so a screen can update or delete it later. It is dynamic because Hive keys may be int or String.
  • defaultValue — used when an old record does not have that field yet.
  • Uint8List? — the photo's bytes; null means "no photo".

2. Generate the Adapter

bash
dart run build_runner build --delete-conflicting-outputs

This creates data_objects.g.dart containing DataObjectsAdapter. Run it again every time you add or change a field. While developing you can use watch instead of build.

3. Rules That Protect Saved Data

RuleWhy
Never reuse or renumber a @HiveFieldOld records would load into the wrong fields
Never change typeIdHive could not find the adapter
Add new fields with new numbers and a defaultValueOld records still open
Do not edit .g.dartIt is overwritten on the next build

4. Register the Adapter

An adapter must be registered once before its box is opened:

dart
Hive.registerAdapter(DataObjectsAdapter());

We do that inside the manager in Lecture 004, guarded by isAdapterRegistered.


Code Examples

Example 1 — Add a New Field Later

Suppose we want an age. Next free number is 5:

dart
@HiveField(5, defaultValue: 0)
int age = 0;

Run build_runner again. Records saved before the change load with age == 0 — nothing is lost.


Common Beginner Mistakes

1. Forgetting part '...g.dart' — the generator has nowhere to write; the analyzer complains that DataObjectsAdapter does not exist.

2. Not running build_runner — the .g.dart file is missing, so DataObjectsAdapter is undefined.

3. Renumbering fields — swapping @HiveField(1) and (2) makes old names load as addresses. Numbers are forever.

4. Registering the adapter twice — Hive throws. Guard with Hive.isAdapterRegistered.


Best Practices

  • Give every non-nullable field a defaultValue.
  • Keep a comment of the highest field number used.
  • Store large blobs (images) sparingly — see Lecture 007.

Mini Challenge

Add @HiveField(5, defaultValue: 0) int age, regenerate, and open data_objects.g.dart to find where age appears in both read and write.


Practice Questions

  1. What does typeId identify? 2. Why numbers instead of names? 3. Which command creates the adapter? 4. What happens to old records when you add a field with a default?

Practice Answers

  1. The class, uniquely, inside the app.
  2. Numbers keep old data readable if a field is renamed.
  3. dart run build_runner build --delete-conflicting-outputs.
  4. They load normally and the new field gets its default.

Key Takeaways

  • @HiveType + @HiveField describe the class; build_runner writes the adapter.
  • Field numbers and typeId never change; new fields get new numbers.
  • Register the adapter before opening the box.

Video lecture

Lecture 003 · 22 min