On this page14 sections
Lecture 003 — The Model Class & Type Adapter
| Category | 2 — Models & Manager |
| Lecture | 003 of 007 |
| Estimated video length | 22 min |
| Target | Flutter 3.44 · Dart 3.12 · hive 2.2 |
| Level | Beginner |
| Video | Part 1 — Introduction, Setup, Model Adapters & Manager Classes |
| Source code | GitHub — 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
@HiveTypeand fields with@HiveField - Run
build_runnerto generate the adapter - Choose
typeIdand field numbers, and know why they must never change - Give fields
defaultValues so old records still load
1. The Model Class
// 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 isdynamicbecause Hive keys may beintorString.defaultValue— used when an old record does not have that field yet.Uint8List?— the photo's bytes;nullmeans "no photo".
2. Generate the Adapter
dart run build_runner build --delete-conflicting-outputsThis 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
| Rule | Why |
|---|---|
Never reuse or renumber a @HiveField | Old records would load into the wrong fields |
Never change typeId | Hive could not find the adapter |
Add new fields with new numbers and a defaultValue | Old records still open |
Do not edit .g.dart | It is overwritten on the next build |
4. Register the Adapter
An adapter must be registered once before its box is opened:
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:
@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
- What does
typeIdidentify? 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
- The class, uniquely, inside the app.
- Numbers keep old data readable if a field is renamed.
dart run build_runner build --delete-conflicting-outputs.- They load normally and the new field gets its default.
Key Takeaways
@HiveType+@HiveFielddescribe the class;build_runnerwrites the adapter.- Field numbers and
typeIdnever change; new fields get new numbers. - Register the adapter before opening the box.