Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
Any mobile application depends on data persistence. We should manage the data between the application launches and our local storage. There are various methods to achieve this. SQLite, SQFLite can be used for this purpose if we want relational data. But, if we wish to have a faster local NoSQL database, we can use Hive. We can easily integrate it with our Flutter applications.
In this article, we will study Hive Flutter.
What is Hive?
Hive Flutter is a lightweight and Dart-based database. It is used for local storage. It is safe, quick, and, more importantly, independent of any native dependencies. It has cross-platform support, which handles mobiles, desktops, and browsers. It is both powerful and straightforward to use. It has built-in solid encryption that makes it safe and secure. Hive Flutter is at par with SharedPreferences regarding speed when reading data. But, when it comes to writing or updating data, Hive Flutter performs much better.
So, it is a fast, NoSQL database for Flutter applications. It does not require a complex setup and, thus, is simple and efficient.
Setting up Hive
For setting up Hive Flutter in your application, first, add the following dependencies in your dependencies section in the pubsec.yml file:
Then, you can run the following command to download the packages:
flutter pub get
Boxes in Hive
All the data in Hive Flutter is organized and stored in boxes. It may be compared to a table in SQL, but it has no fixed structure and can store anything.
A single box may be enough for small applications. And these are encrypted for security.
Open Box
A box needs to be open to be used. It loads all the data from the local storage into the memory for the application's immediate use.
The command for it is as follows:
var box = await Hive.openBox<E>('testBox');
Let us look at the description of different parameters of it:
Parameters
Description
name
It specifies the storage location and checks if a box of the same name or location already exists. It is case-sensitive.
encryptionKey
It is a byte array of size 32 for encryption and decryption of values in the box.
keyComparator
Keys are sorted lexicographically. This parameter allows us to customize that.
compactionStrategy
It helps us specify our rules for automatic compaction.
crashRecovery
If the application gets killed during a writing operation, the last entry is thought to be corrupted and deleted when the application restarts. You can customize it using this parameter if you want to change it.
path
Boxes are stored in the directory allotted to Hive.init(). You can specify the directory with this parameter.
bytes
You can provide the box in a binary form instead of using it as a backend.
Get Open Box
Hive Flutter stores reference to all the open boxes. If you wish to get an already opened box, you can use the following command:
var box = Hive.box('myBox');
Close Box
If you don't require a box again, you should close it. On closing a box, it removes all its cache files and values. But if your application is running, leave the box open.
var box = await Hive.openBox('myBox');
await box.put('hello', 'world');
await box.close();
Before exiting, you should close the box in use.
Type parameter: Box<E>
You can specify the type of values for a box. An example of opening a box is as follows:
var box = await Hive.openBox<User>('users');
box.add(User());
box.add(5); // Compile time error
The upper box can also contain subtypes of User. But, it is important to note that you must provide the same type parameter to the Hive.Box(). The same box cannot be opened multiple times with different parameters.
Lazy Box
As soon as a box is opened, all the box's content is stored in the memory. It works well for small applications but is not advisable for large ones. For larger applications, values are loaded lazily. When a lazy box opens, its keys are stored in the memory, and once the user wants to access some file, it is read from the disk storage.
var lazyBox = await Hive.openLazyBox('myLazyBox');
var value = await lazyBox.get('lazyVal');
Also, to get an already opened lazy box, use the following command:
var lazyBox = Hive.lazyBox('myLazyBox');
Encrypted Box
Hive Flutter supports AES-256 encryption out of the box to store data on the disk securely. But you need a 256-bit key for that. Hive Flutter provides a function to generate an encryption key securely. You need to pass the key when you wish to open the box:
import 'dart:convert';
import 'package:hive/hive.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
void main() async {
const secureStorage = FlutterSecureStorage();
// if key not exists return null
final encryptionKeyString = await secureStorage.read(key: 'key');
if (encryptionKeyString == null) {
final key = Hive.generateSecureKey();
await secureStorage.write(
key: 'key',
value: base64UrlEncode(key),
);
}
final key = await secureStorage.read(key: 'key');
final encryptionKeyUint8List = base64Url.decode(key!);
print('Encryption key Uint8List: $encryptionKeyUint8List');
final encryptedBox = await Hive.openBox('vaultBox', encryptionCipher: HiveAesCipher(encryptionKeyUint8List));
encryptedBox.put('secret', 'Hive is cool');
print(encryptedBox.get('secret'));
}
Only values are encrypted, while keys are stored as plain texts. Also, if the key passed is incorrect, some unexpected action will occur.
Initializing Hive
Next is to initialize the Hive Flutter. For it, include the following command in your main function in the main.dart file:
await Hive.initFlutter();
Next, for custom model classes, we can use TypeAdapter to create binary methods for it. It must be registered to use it using the following command:
Hive.registerAdapter(MyObjectAdapter());
An instance of the adapter and a typeID is needed to register a TypeAdapter. When a value comes back from the disk, the typeID is required to identify the proper adapter. The type range is 0 to 233.
You can use the following model class:
import 'package:hive/hive.dart';
class User {
String name;
User(this.name);
@override
String toString() => name; // Just for print()
}
void main() async {
// Register Adapter
Hive.registerAdapter(UserAdapter());
var box = await Hive.openBox<User>('userBox');
box.put('david', User('David'));
box.put('sandy', User('Sandy'));
print(box.values);
}
// Can be generated automatically
class UserAdapter extends TypeAdapter<User> {
@override
final typeId = 0;
@override
User read(BinaryReader reader) {
return User(reader.read());
}
@override
void write(BinaryWriter writer, User obj) {
writer.write(obj.name);
}
}
Also, remember to register every TypeAdapter before unpacking any package. The data types of the data to be written or read should match with that of the boxes. Also, no duplicity should be there in terms of box names. Next, all TypeAdapters should be registered before opening any boxes. And typeIDs should be used consistently. Any changes must work with previous iterations.
Data Operations
Let us discuss the operations we can perform on the data using Hive Flutter.
Storing and Fetching Data
Let us see how to read from a box. We can use the following commands:
var box = Hive.box('myBox');
String name = box.get('name');
DateTime birthday = box.get('birthday');
We can use the .get() function for it. If the key does not exist, null is returned.
Also, we can fetch the data using indexes. Like, use the following command to retrieve the data at the 0th index:
box.getAt(0);
Next, you can store data in the box using the .put() function. Look at the following command:
We can see that we are storing the data using the key-value pairs using the .put() and the .putAll() functions. Note that the keys must be ASCII strings with a maximum length of 255 characters or 32 unsigned-bit integers.
Updating and Deleting Data
Next, let us see how to update and delete data in Hive Flutter. For update, you can use the same .put() function. It will replace the older value for that key with the new value. You can also use the .putAt() function to put values at a specified index.
Next, you can use the .delete() function to delete values in Hive Flutter.
box.delete(‘school’);
You can also use the .deleteAt() function to delete values at a specified index:
box.deleteAt(1);
Good Practices for Hive Flutter
Let us discuss some good practices to follow when using Hive Flutter:
Partitioning: It can improve the Hive query performance. It reduces the amount of data to be scanned. You can divide your data by any relevance you like.
Bucketing: It helps you group the data based on some condition. It reduces the amount of data to be scanned.
File Formats: Some file formats in Hive Flutter are more efficient than others. Like, Parquet and ORC are optimal for storage and performance.
Frequently Asked Questions
What is Flutter?
Flutter is an open-source software development kit. Google developed it. It enables users to build cross-platform applications for web browsers, Android, iOS, Linux, MacOS, Windows, etc.
What is Hive Flutter?
Hive Flutter is a lightweight and Dart-based database. It is used for local storage. It is safe, quick, and independent of any native dependencies. It has cross-platform support, which handles mobiles, desktops, and browsers. It is both powerful and straightforward to use.
What do you mean by auto-increment and indices in Hive Flutter?
It means you can use indices of key-value pairs for writing, reading, and deleting values in Hive Flutter. You can use .putAt(), .getAt(), and .deleteAt() functions for it. Hive Flutter supports 0-based indexing. By default, string keys are lexicographically sorted.
Conclusion
Hive Flutter is a lightweight, fast, and secure NoSQL database for Flutter applications. It helps store data in the local storage for application launches and functionalities. In this article, we studied its definition, initialization, use, the boxes used in it, CRUD operations for it, and good practices to follow when dealing with it.
If you want to learn more about it, do read the following articles: