Flutter Hive
Lightning-fast NoSQL database for Flutter
⚡ What is Hive?
Hive is a lightweight, blazing-fast NoSQL database written in pure Dart. It requires no native dependencies, works seamlessly across all platforms, and stores data in key-value boxes with excellent performance for mobile applications.
// Add to pubspec.yaml
dependencies:
hive: ^2.2.3
hive_flutter: ^1.1.0
// Initialize and use
await Hive.initFlutter();
var box = await Hive.openBox('myBox');
Key Features
Super Fast
Faster than SQLite and Shared Preferences
box.put('key', value);
// Instant write
No SQL
Simple key-value storage
var value = box.get('key');
Type Safe
Store custom objects easily
box.put('user',
User(name: 'John'));
Encryption
Built-in encryption support
Hive.openBox('secure',
encryptionKey: key);
🔹 Installation
Add Hive packages to your project:
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
hive: ^2.2.3
hive_flutter: ^1.1.0
dev_dependencies:
hive_generator: ^2.0.1
build_runner: ^2.4.6
hive_generator
is optional, needed only for custom objects
🔹 Initialize Hive
Set up Hive in your app:
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
void main() async {
// Initialize Hive
await Hive.initFlutter();
// Open a box
await Hive.openBox('settings');
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hive Demo',
home: HomePage(),
);
}
}
Result:
✅ Hive initialized and box opened
🔹 Basic Operations
Store and retrieve data from Hive:
// Get the box
var box = Hive.box('settings');
// Write data
await box.put('username', 'JohnDoe');
await box.put('age', 25);
await box.put('isDarkMode', true);
await box.put('score', 95.5);
// Read data
String? username = box.get('username');
int age = box.get('age', defaultValue: 0);
bool isDarkMode = box.get('isDarkMode') ?? false;
print('Username: $username');
print('Age: $age');
print('Dark Mode: $isDarkMode');
// Delete data
await box.delete('username');
// Check if key exists
bool hasKey = box.containsKey('username');
// Get all keys
Iterable keys = box.keys;
// Clear all data
await box.clear();
Output:
Username: JohnDoe
Age: 25
Dark Mode: true
🔹 Storing Custom Objects
Create a type adapter for custom classes:
import 'package:hive/hive.dart';
part 'person.g.dart'; // Generated file
@HiveType(typeId: 0)
class Person extends HiveObject {
@HiveField(0)
String name;
@HiveField(1)
int age;
@HiveField(2)
String email;
Person({required this.name, required this.age, required this.email});
}
// Register adapter and use
void main() async {
await Hive.initFlutter();
// Register the adapter
Hive.registerAdapter(PersonAdapter());
// Open box for Person objects
var box = await Hive.openBox<Person>('people');
// Add person
var person = Person(name: 'Alice', age: 28, email: '[email protected]');
await box.add(person);
// Get person
Person? firstPerson = box.getAt(0);
print('Name: ${firstPerson?.name}');
}
Run
flutter packages pub run build_runner build
to generate adapter
🔹 Lazy Box
For large data, use lazy boxes to load data on demand:
// Open lazy box
var lazyBox = await Hive.openLazyBox('largeData');
// Write data (same as regular box)
await lazyBox.put('bigFile', largeData);
// Read data (async operation)
var data = await lazyBox.get('bigFile');
// Close when done
await lazyBox.close();
Lazy boxes don't load all data into memory at once
🔹 Complete Example
A todo app using Hive:
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
class TodoPage extends StatefulWidget {
@override
_TodoPageState createState() => _TodoPageState();
}
class _TodoPageState extends State<TodoPage> {
late Box todoBox;
final TextEditingController _controller = TextEditingController();
@override
void initState() {
super.initState();
todoBox = Hive.box('todos');
}
void addTodo() {
if (_controller.text.isNotEmpty) {
todoBox.add(_controller.text);
_controller.clear();
setState(() {});
}
}
void deleteTodo(int index) {
todoBox.deleteAt(index);
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Hive Todo')),
body: Column(
children: [
Padding(
padding: EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(hintText: 'Enter todo'),
),
),
IconButton(
icon: Icon(Icons.add),
onPressed: addTodo,
),
],
),
),
Expanded(
child: ValueListenableBuilder(
valueListenable: todoBox.listenable(),
builder: (context, Box box, widget) {
return ListView.builder(
itemCount: box.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(box.getAt(index)),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => deleteTodo(index),
),
);
},
);
},
),
),
],
),
);
}
}
🔹 Best Practices
- Open Once: Open boxes once and reuse them
- Close Boxes: Close boxes when no longer needed
- Use TypeId: Assign unique typeIds to adapters
- Lazy Boxes: Use for large datasets
- Compact: Periodically compact boxes to save space