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

🧠 Test Your Knowledge

What makes Hive different from SQLite?