Flutter – Store Data in Hive Local Database
Hive is a data storage in our phone where we can store data in boxes. We can store an integer, string, list of strings, Boolean, double, models, list of integers, etc. in Hive. Now let us discuss where we can implement these. The first we can use this is to save the user information user is logged in or not, and any id or user details so that users don’t have to log in again whenever a user open that app. You can store bigger data also but it will store for a particular device only. Hive is a NoSQL server where you can store a maximum number of data in any form.
Difference Between SharedPreferences and Hive
Hive |
Shared Preferences |
---|---|
Store Maximum data in it |
Limited to store smaller data |
Store Data in any type of datatypes |
Limited to some datatypes |
Useful for Storing larger data |
Useful for storing small data |
Both works well.Its upto your requirement to choose which one is best suitable for you. For Shared Preferences you can refer this amazing article Flutter – SharedPreferences
Implementation
Step 1: Create a basic flutter project by command
Dart
flutter create . |
Step 2: Add hive package in it
Dart
flutter pub add hive_flutter |
Check latest package: https://pub.dev/packages/hive_flutter
Tips Add from visual studio code by Ctrl+shift+P or Command+shift+P then add dependency and type hive and enter.
Step 3: Initialise box you want to use for storing the data
Dart
Future main() async { // It is used so that void main function // can be intiated after successfully // intialization of data WidgetsFlutterBinding.ensureInitialized(); // To intialise the hive database await Hive.initFlutter(); runApp( const MyApp()); } |
It is better to keep it null So that it can manage itself for every platform
Step 4: Open the Box in main function
Dart
Future main() async { // It is used so that void main function can // be intiated after successfully intialization of data WidgetsFlutterBinding.ensureInitialized(); // To intialise the hive database await Hive.initFlutter(); // To open the user hive box await Hive.openBox(userHiveBox); runApp( const MyApp()); } |
Basic UI for doing the CRUD operation
On first screen I will add 1 floating action button will add value to hive database and will have list where list which will show the saved value in hive and in that list tile there will be two button for edit and delete items/users and 1 variable for list stored in database.
Dart
import 'package:flutter/material.dart' ; import 'package:hive_flutter_templates/hive_functions.dart' ; class MainScreen extends StatefulWidget { const MainScreen({super.key}); @override State<MainScreen> createState() => _MainScreenState(); } class _MainScreenState extends State<MainScreen> { // Local Variable Where we save // the hive data of current context List myHiveData = []; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text( "CRUD Operations" ), actions: [ // To refreah the Data stored in Hive IconButton( onPressed: () { }, icon: const Icon(Icons.refresh)) ], ), // To add or create the data in Hive floatingActionButton: FloatingActionButton.extended( label: const Text( "Add Data" ), icon: const Icon(Icons.add), onPressed: () { }), body: Padding( padding: const EdgeInsets.all(8.0), child: myHiveData.isEmpty // To show when no data is stored ? const Center( child: Text( "No Data is Stored" , style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600), )) // To show when data is stored : Column( children: List.generate(myHiveData.length, (index) { final userData = myHiveData[index]; return Card( child: ListTile( title: // Show Name of user stored in data base Text( "Name : ${userData[" name "]}" ), subtitle: // Show Email of user stored in data base Text( "Email : ${userData[" email "]}" ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ // To edit the data stored IconButton( onPressed: () { }, icon: const Icon(Icons.edit)), // To delete the data stored IconButton( onPressed: () { }, icon: const Icon(Icons. delete )), ], ), ), ); }).toList()), )); }} |
Let’s start doing CRUD operations for data storing in Hive
To add or update the data we will create 1 form which will open as bottom dialog box.
Dart
// TextFields' controllers for adding or updating data final TextEditingController _nameController = TextEditingController(); final TextEditingController _emailController = TextEditingController(); // dialog box to create or update the data in hive void showForm( int ? itemKey) async { // itemKey == null -> create new item // itemKey != null -> update an existing item if (itemKey != null) { // To find the existing item // in our local database final existingItem = myHiveData.firstWhere((element) => element[ 'key' ] == itemKey); _nameController.text = existingItem[ 'name' ]; _emailController.text = existingItem[ 'email' ]; } showModalBottomSheet( context: context, elevation: 5, isScrollControlled: true , builder: (_) => Container( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, top: 15, left: 15, right: 15), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Text( itemKey == null ? 'Create New' : 'Update' , style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w600), )), TextField( controller: _nameController, decoration: const InputDecoration(hintText: 'Name' ), ), const SizedBox( height: 10, ), TextField( controller: _emailController, keyboardType: TextInputType.number, decoration: const InputDecoration(hintText: 'Email' ), ), const SizedBox( height: 20, ), ElevatedButton( onPressed: () async { // Save new item if (itemKey == null) { HiveFunctions.createUser({ "email" : _emailController.text, "name" : _nameController.text }); } // update an existing item if (itemKey != null) { HiveFunctions.updateUser(itemKey, { "email" : _emailController.text, "name" : _nameController.text }); } // Clear the text fields _nameController.text = '' ; _emailController.text = '' ; Navigator.of(context).pop(); // Close the bottom sheet // To refresh the Data stored in Hive after updation getHiveData(); }, child: Text(itemKey == null ? 'Create New' : 'Update' ), ), const SizedBox( height: 15, ) ], ), )); } |
For better coding and understanding we will write all the hive functions in one class as separate file named as hive_functions.dart.
Dart
import 'package:hive_flutter/hive_flutter.dart' ; import 'package:hive_flutter_templates/hive_box_constant.dart' ; class HiveFunctions { // Box which will use to store the things static final userBox = Hive.box(userHiveBox); } |
Additionally we are using 1 more file for storing all box name so that we cannot have any confusion.
Dart
const String userHiveBox= "User Box" ; // Constant Name of Box where we will store details of user |
Now we will add all the hive functions in the file named as hive_functions.dart
1. Create: This will create the box or added data in box
Sample Code
Dart
// Create or add single data in hive static createUser(Map data) { userBox.add(data); } // Create or add multiple data in hive static addAllUser(List data) { userBox.addAll(data); } |
2. Read: To read the data you have stored
Dart
// Get All data stored in hive static List getAllUsers() { final data = userBox.keys.map((key) { final value = userBox.get(key); return { "key" : key, "name" : value[ "name" ], "email" : value[ 'email' ]}; }).toList(); return data.reversed.toList(); } // Get data for particular user in hive static Map getUser( int key) { return userBox.get(key); } |
3. Update: Update the data which is already store
Dart
// update data for particular user in hive static updateUser( int key, Map data) { userBox.put(key, data); } |
4. Delete: Delete the data which is stored already
Dart
// delete data for particular user in hive static deleteUser( int key) { return userBox. delete (key); } // delete data for particular user in hive static deleteAllUser( int key) { return userBox.deleteAll(userBox.keys); } |
Source code for all functions is here
Dart
import 'package:hive_flutter/hive_flutter.dart' ; import 'package:hive_flutter_templates/hive_box_constant.dart' ; class HiveFunctions { // Box which will use to store the things static final userBox = Hive.box(userHiveBox); // Create or add single data in hive static createUser(Map data) { userBox.add(data); } // Create or add multiple data in hive static addAllUser(List data) { userBox.addAll(data); } // Get All data stored in hive static List getAllUsers() { final data = userBox.keys.map((key) { final value = userBox.get(key); return { "key" : key, "name" : value[ "name" ], "email" : value[ 'email' ]}; }).toList(); return data.reversed.toList(); } // Get data for particular user in hive static Map getUser( int key) { return userBox.get(key); } // update data for particular user in hive static updateUser( int key, Map data) { userBox.put(key, data); } // delete data for particular user in hive static deleteUser( int key) { return userBox. delete (key); } // delete data for particular user in hive static deleteAllUser( int key) { return userBox.deleteAll(userBox.keys); } } |
Now we will call different functions on different onClick and initstate.
- We will call getAll function in initState
- Show form function in floating action button
- Update function in edit button
- Delete function in delete button.
Final Source Code after functions and UI
Dart
import 'package:flutter/material.dart' ; import 'package:hive_flutter_templates/hive_functions.dart' ; class MainScreen extends StatefulWidget { const MainScreen({super.key}); @override State<MainScreen> createState() => _MainScreenState(); } class _MainScreenState extends State<MainScreen> { // Local Variable Where we save // the hive data of current context List myHiveData = []; // TextFields' controllers for adding or updating data final TextEditingController _nameController = TextEditingController(); final TextEditingController _emailController = TextEditingController(); // To Update the data from Hive in local variable getHiveData() { myHiveData = HiveFunctions.getAllUsers(); setState(() {}); } @override void initState() { super.initState(); // Update the initial data // when page is loading getHiveData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text( "CRUD Operations" ), actions: [ // To refreah the Data stored in Hive IconButton( onPressed: () { getHiveData(); }, icon: const Icon(Icons.refresh)) ], ), // To add or create the data in Hive floatingActionButton: FloatingActionButton.extended( label: const Text( "Add Data" ), icon: const Icon(Icons.add), onPressed: () { showForm(null); }), body: Padding( padding: const EdgeInsets.all(8.0), child: myHiveData.isEmpty // To show when no data is stored ? const Center( child: Text( "No Data is Stored" , style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600), )) // To show when data is stored : Column( children: List.generate(myHiveData.length, (index) { final userData = myHiveData[index]; return Card( child: ListTile( title: //Show Name of user stored in data base Text( "Name : ${userData[" name "]}" ), subtitle: //Show Email of user stored in data base Text( "Email : ${userData[" email "]}" ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ // To edit the data stored IconButton( onPressed: () { showForm(userData[ "key" ]); }, icon: const Icon(Icons.edit)), // To delete the data stored IconButton( onPressed: () { HiveFunctions.deleteUser(userData[ "key" ]); // To refreah the Data stored in Hive after deletion getHiveData(); }, icon: const Icon(Icons. delete )), ], ), ), ); }).toList()), )); } // dialog box to create or update the data in hive void showForm( int ? itemKey) async { // itemKey == null -> create new item // itemKey != null -> update an existing item if (itemKey != null) { // To find the existing item in our local database final existingItem = myHiveData.firstWhere((element) => element[ 'key' ] == itemKey); _nameController.text = existingItem[ 'name' ]; _emailController.text = existingItem[ 'email' ]; } showModalBottomSheet( context: context, elevation: 5, isScrollControlled: true , builder: (_) => Container( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, top: 15, left: 15, right: 15), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Text( itemKey == null ? 'Create New' : 'Update' , style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w600), )), TextField( controller: _nameController, decoration: const InputDecoration(hintText: 'Name' ), ), const SizedBox( height: 10, ), TextField( controller: _emailController, keyboardType: TextInputType.number, decoration: const InputDecoration(hintText: 'Email' ), ), const SizedBox( height: 20, ), ElevatedButton( onPressed: () async { // Save new item if (itemKey == null) { HiveFunctions.createUser({ "email" : _emailController.text, "name" : _nameController.text }); } // update an existing item if (itemKey != null) { HiveFunctions.updateUser(itemKey, { "email" : _emailController.text, "name" : _nameController.text }); } // Clear the text fields _nameController.text = '' ; _emailController.text = '' ; Navigator.of(context).pop(); // Close the bottom sheet // To refresh the Data stored in Hive after updation getHiveData(); }, child: Text(itemKey == null ? 'Create New' : 'Update' ), ), const SizedBox( height: 15, ) ], ), )); } } |
Output
Image
1. Basic UI screen
2. Form where we can add or update the data
Video
Errors
1. Unhandled Exception: HiveError: You need to initialize Hive or provide a path to store the box.
Solution : You forgot to initialise the hive in main function
2. The following HiveError was thrown building Builder:
Box not found. Did you forget to call Hive.openBox()?
Solution : You forgot to open the box.
3. Unhandled exception: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/hive_flutter)
Solution: Uninstall the application and reinstall it.
Contact Us