5103
How to Handle Offline Data Storage with Flutter Hive
14 Feb, 2023
7 min read
5103
14 Feb, 2023
7 min read
Table of content
When you develop Flutter applications, you can use online real-time synchronization with the database or offline synchronization. While online synchronization of data will ensure users can access data in real-time, the offline synchronization method is helpful for apps that can access data even in the offline mode.
For that, there are several Flutter database options SQLite, text/JSON files, Objectbox, shared preferences storage, and Hive database. In this blog, we will discuss one of the popular offline synchronization methods using the Flutter Hive database.
Want to learn how you should handle offline Hive storage? This is the blog for you!
Let’s see.
Hive is a fast and lightweight key-value database written in Dart programming language. Since it is programmed keeping Flutter in mind, it can be seamlessly used as a data store for your Flutter application.
If your app doesn’t need real-time data synchronization and needs the data to be stored in the device, Hive database could be a preferable choice for you.
However, there are many alternatives available in the market today we have compared Hive with one of its competitor, Spark.
So, how do we compare Spark vs Hive? Let’s check!
Hive | Spark |
---|---|
It’s a database, much like an RDBMS database, but the data is stored in boxes. | It’s not a database but a data analytics framework. |
Since it supports ANSI SQL standard, the hive integration capabilities are much higher. You can integrate it with databases like Cassandra and HBase. | It can be integrated with Hive, MongoDB, and HBase. |
Since we are looking for ways to handle offline data storage with Flutter app development, we will explore more about Hive going forward.
It is possible to use Hive like a map without awaiting Futures, like this:
var box = Hive.box('myBox');
box.put('name', 'David');
var name = box.get('name');
print('Name: $name');
With Hive, you can perform CRUD (Create, read, update, and delete) operations seamlessly. Here, look at some of the key features of Hive.
Read Also: Cross-platform App Development: Should Startups Invest in it or Not?
Clearly, a hive database is quite a catch if you want to store data offline and retrieve it. But, how can you do so? It starts with the installation of hive and hive Flutter plugins.
Here, we will talk about using the Hive database with the help of TypeAdapter. The below steps will help you create a simple one-page Flutter application with offline handling of data. You will get to explore more about CRUD operations.
It begins with the installation of dependencies such as Hive and Hive Flutter. To do so, you will have to add these packages to pubspec.yaml by writing the following code:
dependencies:
Flutter:
sdk: flutter
hive: ^2.2.3
hive_flutter: ^1.1.0
Then, add the development dependencies as below:
dev_dependencies:
flutter_test:
sdk: flutter
hive_generator: ^1.1.3
build_runner: ^2.2.0
Before you call RunApp in Flutter, you will need to initialize Hive by writing below piece of code:
void main() async {
/*... */
await Hive.initFlutter();
/*...*/
}
“OR”
void main() async{
WidgetsFlutterBinding.ensureInitialized();
// This basically initializes the Flutter Hive with a valid directory in your application files
await Hive.initFlutter();
runApp(const MyApp());
}
In Hive NoSQL, everything is stored and organized in boxes. To understand what these boxes are, you can simply compare them with the tables used in SQL.
However, unlike tables, they do not have any structure and can contain almost every kind of data. Here’s how you can work with a box in Hive!
To open a box, write:
await Hive.openBox('tool_box'); // Well, the name depends on you, change it as you please
When you open a box, all the data stored in Flutter local storage is loaded into the memory so users can access it immediately. You also don’t need to use await/async for retrieving data synchronously.
To retrieve data from box:
final myBox = Hive.box('tool_box');
final something = myBox.get('my_key');
To add new data/item to the box:
await myBox.put('some_key', someValue);
Update an existing data/item by writing:
await myBox.put('some_key', someValue);
Delete an item from the box using this code:
await myBox.delete('some_key');
To add a list of items in the Hive box, you can use the increment keys. Here, the keys will generate automatically and increment in the same way starting from ‘0’.
final listBox = Hive.box('my_list');
int newKey = await listBox.add(someData);
If you want to retrieve all of the keys from Hive boxes, you can do so by writing following piece of code:
final keys = listBox.keys;
final values = listBox.values;
You may as well use loops with the ‘Values’ and ‘Keys’ as required. And, if you need to set keys by yourself, you can use DateTime.now().toString().
These steps should help you code a Flutter app with Hive database. However, if you feel the coding and steps to be difficult, you can further hire Flutter developer to assist you with the app development.
In this piece of code, several users with information like name, designation, and address are mentioned.
import 'package:hive/hive.dart';
part ‘user_model.g.dart’; // Used for generating TypeAdapter
@HiveType(typeId: 0) // So that generator gets an idea that it is a TypeAdapter
class UserModel extends HiveObject {
@HiveField(0) // annotating class field with their corresponding index values
final String name;
@HiveField(1)
final String designation;
@HiveField(2)
final String address;
UserModel({
required this.name,
required this.designation,
required this.address,
});
}
**Note: Since we are using the package hive_generator here, we do not need to construct the TypeAdapter manually.
If you want to build a TypeAdapter class, write this:
flutter packages pub run build_runner build
So, if your file name is user_demo.dart, you will get a file named user_demo.g.dart, where ‘g’ indicates that the file is generated successfully.
Now, you need to register UserDemoAdapter.
void main() async{
WidgetsFlutterBinding.ensureInitialized(); // Initializes Hive with a valid directory in your app files await Hive.initFlutter(); // Register Hive Adapter
Hive.registerAdapter(UserDemoAdapter()); // open box await Hive.openBox
Creating data
You just have to call the add() function to add data in Hive. By using this method, a pair of key values is accepted.
// Adding a new user
Future addUser({required UserModel userModel}) async {
await box.add(userModel); }
After you click on the floating button, you will be able to see a dialog box. You can enter name, designation, and address (or any other details based on what you need) and click the ‘Add’ button. You should be able to see the data then.
You can also use ‘ValuelistenableBuilder()’ to check what’s happening inside a Hive box.
Retrieving Hive data
You can use the get() function to read the box objects. To retrieve the object value, you will have to provide the key by writing:
var userHobby = box.get('hobby');
However, if you use auto incrementing values, you will need to utilize the getAt(index) method for retrieving data.
var userData = box.getAt(index);
ValueListenableBuilder(
valueListenable: HiveDataStore.box.listenable(),
builder: (context, Box box, widget) {
return SafeArea(
child: box.length > 0 ? ListView.builder(
shrinkWrap: true,
itemCount: box.length,
itemBuilder: (BuildContext context, int index) {
var userData = box.getAt(index);
return Container(
padding: const EdgeInsets.all(10),
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(color: Colors.grey.withOpacity(0.1),
border: Border.all(color: Colors.blue.shade900),
borderRadius: const BorderRadius.all(Radius.circular(10))),
child: Row(
children: [
Expanded(
flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IntrinsicHeight(
child: Row(
children: [
Text(userData.name, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w700),
),
VerticalDivider(color: Colors.blue.shade900,thickness: 2,),
Text(userData.description, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w500),
),
],
),
),
const SizedBox(height: 15),
RichText(text: TextSpan(text: 'Hobby: ', style: const TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.w700),
children: [
TextSpan(text: userData.hobby, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
],
),
),
],
),
),
Expanded(
flex: 0,
child: Row(
children: [
InkWell(
onTap:(){
isUpdate.value = true;
nameEditingCtr.text = userData.name;
hobbyEditingCtr.text = userData.hobby;
descriptionEditingCtr.text = userData.description;
_showDialog(context,index);
},
child: Icon(Icons.edit, size: 30, color: Colors.blue.shade900,),
),
const SizedBox(width: 10),
InkWell(
onTap: ()async{
await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Are you sure you want to delete ${userData.name}?'),
actions: [
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue.shade900),
elevation: MaterialStateProperty.all(3),
shadowColor: MaterialStateProperty.all(Colors.blue.shade900), //Defines shadowColor
),
onPressed: () {dataStore.deleteUser(index: index);},
child: const Text('Yes', style: TextStyle(color: Colors.white),
),
),
TextButton(
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.blue.shade900),
elevation: MaterialStateProperty.all(3),
shadowColor: MaterialStateProperty.all(Colors.blue.shade900), //Defines shadowColor
),
onPressed: () {Navigator.of(context, rootNavigator: true).pop(); },
child: const Text('No',
style: TextStyle(color: Colors.white),
),
),
],
),
);
},
child: Icon(Icons.delete,size:30,color: Colors.blue.shade900,))
],
)),
],
),
);
}):const Center(child: Text("No Data Found"),));
}
)
Updating data
You can use the put() to update the existing value of key. To do so, you can write:
// updating user data
Future updateUser({required int index,required UserModel userModel}) async {
await box.putAt(index,userModel); }
Deleting data
Passing the key to the delete() will help delete data.
// delete user
Future deleteUser({required int index}) async {
await box.deleteAt(index); }
Here, the auto incrementing values method is used for deleting data in Hive. You can also utilize deleteAt(index) method for fleeting values using the index.
Flutter saves data locally with the help of Hive and it is one of the many advantages of the SDK. You can also check our Flutter pros and cons blog for more information.
With Flutter Hive, you will be able to manage offline data storage more seamlessly. It is an efficient way of managing data offline. So, if you want to build a simple app that requires offline data creation, retrieval, update, and delete, you can check out the steps mentioned here.
Furthermore, if you need any help with programming, you can trust our developers with the same. BiztechCS boasts a team of Flutter developers who are well versed in database technologies like Hive.
So, what are you waiting for? Connect with our team today!
Development
Laravel
128
By Devik Gondaliya
22 Aug, 2024
Development
Devops
125
By Biztech
20 Aug, 2024
Javascript
248
By Devik Gondaliya
13 Aug, 2024