Hive — Not The Bee!

Jesutoni Aderibigbe
6 min readFeb 6, 2024

--

Remember this cartoon?

Last week, I shared with my Flutter community members about local storage for their mobile applications while using Hive.

In Flutter, local storage refers to the methods your app can save data on the user’s device itself, instead of relying on a remote server. It is useful for the following purposes:

  1. Offline Data Access: Local storage allows your Flutter application to store data on the device, enabling users to access it even when they are offline. This is crucial for apps that need to provide functionality regardless of internet connectivity.
  2. Improved Performance: Reading and writing data locally is generally faster than making network requests. This can lead to improved performance and a better user experience, especially for apps that require quick access to data.
  3. Reduced Dependency on Network: Storing data locally reduces the reliance on network availability and speed. It ensures that your app can function independently of the network status, making it more robust and reliable.
  4. Persistent User Preferences: Local storage is commonly used to store user preferences and settings. This allows users to have a personalized experience even after they close and reopen the app.
  5. Faster Load Times: By caching certain data locally, your app can load faster because it doesn’t need to fetch the same data from the server every time. This is particularly useful for static content that doesn’t change frequently.

There are several packages made in and from the Flutter community that help save data locally in your user’s app. These packages are(but not limited to)

  • Shared Preferences
  • Sqlflite
  • Hive

USING HIVE IN YOUR FLUTTER APPLICATION

Hive is a very simple package to use. You can get it set up in a couple of minutes. To use Hive, follow these steps:

  1. Add dependencies to the pubspec.yaml
flutter pub add hive
flutter pub add hive_flutter
dart pub add hive_generator
dart pub add dev:build_runner

OR, add the following lines to your pubspec.yaml

dependencies:
hive: ^2.2.2
hive_flutter: ^1.1.0

dev_dependencies:
hive_generator: ^1.1.3
build_runner: ^2.2.0

2. Generate Type Adapters: Imagine Hive as a special storage box that can hold different kinds of toys. It can easily store simple toys like blocks and balls on its own. But for more complex toys like puzzles or action figures with many parts, it needs a special tool called a type adapter. Without the right type of adapters, Hive might get confused and mix up the parts of those complex toys, making them unusable. So, it’s important to have the right adapters for each kind of toy you want to store in Hive’s box.

In real life, type adapters help Hive work with your custom data models, which are like complex toys. They make sure Hive can save and retrieve all the information about your models perfectly, even if they have many fields or special properties.

Think of it like this:

  • Simple data types (like numbers, strings, and lists) are like blocks and balls — Hive can handle them without help.
  • Custom data models (like your Person class with name and age) are like puzzles or action figures—Hive needs type adapters to manage them properly.

To create a Hive Type Adapter

  • Create a new Dart file (e.g., models.dart) to define your data models.
  • For each model, you want to store in Hive, create a corresponding class and annotate it with @HiveType().
import 'package:hive/hive.dart';

part 'models.g.dart'; // Generated file

@HiveType(typeId: 1)
class Person {
@HiveField(0)
String name;
@HiveField(1)
int age;

Person(this.name, this.age);
}
  • Run flutter packages pub run build_runner build to generate the necessary type adapters automatically without having to write boilerplate code again and again.

3. Initialize Hive: In your main() function, before running your app, initialize Hive:

import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'models.dart'; // Import your models

void main() async {
await Hive.initFlutter();
Hive.registerAdapter(PersonAdapter()); // Register your adapters
runApp(MyApp());
}

NOTE: Hive stores data in “boxes,” which are like separate databases. You could open, delete, read from, write into, and update data in those boxes.

TO OPEN A BOX

var box = await Hive.openBox('myBox');

The method .openBox takes a name parameter which helps identify your box. You could name it however you would love. In this case, we named it “myBox”. This is done after you have initialized hive in your flutter application.

OR

You could decide to create a separate folder to handle all that you would need for your business logic.

import 'package:hive/hive.dart';

Future<void> openBox() async {
await Hive.openBox<MyModel>('myBox');
}

TO SAVE A BOX

Use the put() method to add data to a box:

box.put('name', 'John Doe');
box.put('age', 30);
box.put('person', Person('Alice', 25));

The put method takes two parameters; key-value data. “key”: “name” and “value”: “John Doe”

OR, in your file that handles the business logic of your application, you could define your function

Future<void> saveData(String key, String value) async {
var box = await Hive.openBox<Person>('myBox');
var myModel = Person()..key = key..value = value;
await box.add(myModel);
}

TO READ FROM A BOX

Use the get() method to retrieve data from a box:

var name = box.get('name');
var person = box.get('person');

OR

Future<List<Person>> readData() async {
var box = await Hive.openBox<Person>('myBox');
return box.values.toList();
}

TO DELETE FROM A BOX

Use the delete() method to delete data from a box:

box.delete('key');

This helps to remove a specific piece of data by its key

box.deleteAll(keys);

This would delete multiple entries at once.

var keysToRemove = ['key1', 'key2', 'key3'];
box.deleteAll(keysToRemove);

This provides a list of keys to remove.

OR

Future<void> deleteData(String key) async {
var box = await openBox();

// Find the index of the item with the given key
var index = box.values.toList().indexWhere((element) => element.key == key);

if (index != -1) {
// If the item is found, delete it from the box
await box.deleteAt(index);
print('Data with key $key deleted successfully.');
} else {
print('Data with key $key not found.');
}

// Close the box
await box.close();
}

TO CHECK IF A DATA EXISTS

bool keyExists = box.containsKey('key');
if (box.containsKey('name')) {
print('The key "name" exists in the box!');
} else {
print('The key "name" does not exist in the box.');
}

OR

Future<bool> doesKeyExist(String key) async {
var box = await openBox();

// Check if the key exists in the box
bool keyExists = box.containsKey(key);

// Close the box
await box.close();

return keyExists;
}

TO UPDATE DATA

While Hive doesn’t have a direct “update” method, you can effectively update data in a box using the following approach:

  • Use the get() method to fetch the data you want to modify, using its key:
var box = await Hive.openBox('myBox');
var person = box.get('person'); // Assuming a Person object was previously stored
  • Make the necessary changes to the retrieved data:
person.name = 'Updated Name';
person.age = 35;
  • Use the put() method to overwrite the existing data with the modified version:
box.put('person', person);

The full example;

var box = await Hive.openBox('myBox');

var person = box.get('person');
if (person != null) {
person.name = 'New Name';
box.put('person', person);
print('Person data updated successfully!');
} else {
print('Person not found in the box.');
}

OR

Future<void> updateData(String key, String newValue) async {
var box = await openBox();

// Check if the key exists in the box
if (box.containsKey(key)) {
// Retrieve the existing object
var existingObject = box.get(key);

// Update the value of the object
existingObject!.value = newValue;

// Put the updated object back into the box
await box.put(key, existingObject);

print('Data with key $key updated successfully.');
} else {
print('Data with key $key not found. Update failed.');
}

// Close the box
await box.close();
}

You can use this function to update data in the ‘myBox’ Hive box:

await updateData('myKey', 'newUpdatedValue');

CONCLUSION.

The hive package has a very beautiful and detailed documentation that you could use to start building your offline apps.

In our next tutorial, I will be using your practical steps on how to use Hive to build a complete application. Till next time!

--

--