Hive
Cache Library
Hive
Overview
Hive is a lightweight and fast key-value database written in pure Dart. Implemented entirely in Dart, it's optimized as a local data storage solution for Flutter applications. As an alternative to heavy databases like SQLite, it provides a simple API and high performance, working across iOS, Android, desktop, and web platforms.
Details
Hive is a NoSQL database designed for lightweight data persistence in mobile applications. It supports transactions, type safety, and CRUD operations while requiring minimal configuration. Internally, it stores data in binary format to achieve fast read and write performance.
Key Features
- Pure Dart Implementation: Cross-platform support without external dependencies
- High Performance: Fast data access through binary format storage
- Type Safety: Type-safe data operations through generic support
- Transactions: write/read transactions ensuring atomicity
- Auto Key Generation: Automatic increment keys when used in list format
- Custom Object Support: Storage of complex data structures through serialization
- Lightweight: Minimal memory footprint and disk usage
Architecture
- Box: Container for storing data (equivalent to tables)
- Adapter: Serialization/deserialization for custom objects
- Transaction: Transaction control through write() and read()
- Type Safety: Type constraints through generics (
Box<T>)
Pros and Cons
Pros
- Simplicity: Immediate usage with minimal configuration
- High Performance: Faster read/write performance than SQLite
- Type Safety: Bug reduction through compile-time type checking
- Lightweight: Minimal impact on app size
- Cross-Platform: Available on all Flutter-supported platforms
- Offline Support: Data persistence without network connectivity
Cons
- No Complex Queries: Lacks advanced query features like SQL
- No Relational Data: No relational database functionality
- Limited Concurrent Access: Multi-process concurrent access is discouraged
- Not Suitable for Large Data: May not be suitable for large amounts of data
Reference Links
Code Examples
Basic Setup and Box Operations
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Hive
final directory = await getApplicationDocumentsDirectory();
Hive.defaultDirectory = directory.path;
runApp(MyApp());
}
// Basic data operations
void basicOperations() {
// Open default Box
final box = Hive.box();
// Store data
box.put('name', 'Alice');
box.put('age', 25);
box.put('city', 'Tokyo');
// Retrieve data
final name = box.get('name');
final age = box.get('age', defaultValue: 0);
print('Name: $name, Age: $age');
// Map-style operations
box['email'] = '[email protected]';
final email = box['email'];
// Bulk data storage
box.putAll({
'country': 'Japan',
'language': 'Japanese'
});
}
Named Boxes and Type Safety
// Named Box creation
void namedBoxExample() {
final settingsBox = Hive.box(name: 'settings');
final cacheBox = Hive.box(name: 'cache');
// Store settings data
settingsBox.put('theme', 'dark');
settingsBox.put('notifications', true);
// Store cache data
cacheBox.put('lastUpdate', DateTime.now().toIso8601String());
}
// Type-safe Box
void typeSafeExample() {
// Box that stores only String types
final Box<String> stringBox = Hive.box<String>(name: 'strings');
stringBox.put('greeting', 'Hello, World!');
stringBox.put('farewell', 'Goodbye!');
// Compile-time error
// stringBox.put('number', 123); // Error!
// Safe retrieval
final greeting = stringBox.get('greeting') ?? 'Default';
}
List-style Data Operations
void listLikeOperations() {
final box = Hive.box();
// Add data in list format
box.add('First item');
box.add('Second item');
box.add('Third item');
// Retrieve by index
print(box.getAt(0)); // First item
print(box.getAt(1)); // Second item
// Can be mixed with map format
box.put('key1', 'Value by key');
print(box.getAt(3)); // Value by key
// Update by index
box[0] = 'Updated first item';
// Delete data
box.deleteAt(1); // Delete Second item
}
Storing Custom Objects
// Custom class definition
class User {
User({required this.name, required this.email, required this.age});
// Factory constructor from JSON
factory User.fromJson(Map<String, dynamic> json) => User(
name: json['name'] as String,
email: json['email'] as String,
age: json['age'] as int,
);
final String name;
final String email;
final int age;
// Convert to JSON
Map<String, dynamic> toJson() => {
'name': name,
'email': email,
'age': age,
};
@override
String toString() => '$name ($email) - $age years old';
}
void customObjectExample() {
// Register adapter
Hive.registerAdapter('User', User.fromJson);
final box = Hive.box();
// Store custom object
final user = User(
name: 'Bob',
email: '[email protected]',
age: 30,
);
box.put('currentUser', user);
// Retrieve custom object
final retrievedUser = box.get('currentUser') as User?;
print('Retrieved user: $retrievedUser');
}
Transaction Processing
void transactionExample() {
final box = Hive.box();
// Write transaction
box.write(() {
box.put('account1', 1000);
box.put('account2', 500);
box.put('account3', 750);
});
// Read transaction
box.read(() {
final total = (box.get('account1', defaultValue: 0) as int) +
(box.get('account2', defaultValue: 0) as int) +
(box.get('account3', defaultValue: 0) as int);
print('Total balance: $total');
});
// Atomicity example (rollback on error)
box.put('balance', 1000);
try {
box.write(() {
box.put('balance', 500);
throw Exception('Some error occurred');
});
} catch (e) {
print('Error occurred: $e');
}
print('Balance: ${box.get('balance')}'); // 1000 (rolled back)
}
Hive Usage in Flutter App
class TodoApp extends StatefulWidget {
@override
_TodoAppState createState() => _TodoAppState();
}
class _TodoAppState extends State<TodoApp> {
final Box<String> todoBox = Hive.box<String>('todos');
final TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Hive Todo App')),
body: Column(
children: [
// Add new TODO
Padding(
padding: EdgeInsets.all(16.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'Enter TODO',
),
),
),
IconButton(
icon: Icon(Icons.add),
onPressed: () {
if (_controller.text.isNotEmpty) {
setState(() {
todoBox.add(_controller.text);
_controller.clear();
});
}
},
),
],
),
),
// Display TODO list
Expanded(
child: ListView.builder(
itemCount: todoBox.length,
itemBuilder: (context, index) {
final todo = todoBox.getAt(index);
return ListTile(
title: Text(todo ?? ''),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
todoBox.deleteAt(index);
});
},
),
);
},
),
),
],
),
);
}
}
Asynchronous Processing and Isolates
import 'dart:isolate';
void isolateExample() async {
final box = Hive.box();
// Store data in main thread
box.put('message', 'Hello from main');
// Perform Hive operation in different isolate
await Hive.compute(() {
// Access same Box from other isolate
final box = Hive.box();
print(box.get('message')); // Hello from main
// Update data
box.put('message', 'Updated from isolate');
});
// Check in main thread
print(box.get('message')); // Updated from isolate
}
Data Cleanup and Maintenance
void maintenanceOperations() {
final box = Hive.box();
// Delete specific key
box.delete('oldKey');
// Delete multiple keys
box.deleteAll(['key1', 'key2', 'key3']);
// Clear all data
box.clear();
// Check Box size
print('Box size: ${box.length}');
print('Box is empty: ${box.isEmpty}');
// Get all keys
final keys = box.keys.toList();
print('All keys: $keys');
// Get all values
final values = box.values.toList();
print('All values: $values');
}