6/recent/ticker-posts

Hive Database in flutter

Hive is a NoSQL database solution for Flutter applications. It’s a fast, efficient, and lightweight alternative to traditional databases like SQLite. Hive stores data in files on disk, making it ideal for small and medium-sized projects.

To use Hive in your Flutter app, you need to follow these steps:

1. Add the Hive dependency to your pubspec.yaml file:

dependencies:

hive: ^2.2.3
hive_flutter: ^1.1.0
build_runner: ^2.3.3
hive_generator: ^2.0.0
path_provider: ^2.0.14

2.Initialize Hive in your app’s main() function:

await Hive.initFlutter();

This initializes Hive with the default settings. You can also provide a path to the directory where you want to store your Hive data files:

final appDocumentDirectory = await getApplicationDocumentsDirectory();
await Hive.initFlutter(appDocumentDirectory.path);

3.Generate a model class:

Define a model class that will be used to store data in Hive. The class should extend HiveObject and have annotations from the hive package. For example:

import 'package:hive/hive.dart';

part 'person.g.dart';

@HiveType(typeId: 0)

class Person extends HiveObject {
@HiveField(0)
String name;

@HiveField(1)
String fatherName;

@HiveField(2)
String motherName;

Person({required this.name, required this.fatherName, required this.motherName});
}

Note: the part ‘person.g.dart’; line is used to generate a .g.dart file that contains the implementation for the HiveObject and TypeAdapter classes for this model.

4.Generate a TypeAdapter:

A TypeAdapter is used to tell Hive how to convert an instance of the model class to and from bytes that can be stored in the database. To generate a TypeAdapter for the Person model, run the following command in the terminal:

flutter packages pub run build_runner build

flutter packages pub run build_runner build

This will generate the person.g.dart file that contains the implementation for the PersonAdapter class.

5.Register your data model classes with Hive:

Hive.registerAdapter(MyDataModelAdapter());

You need to create a HiveAdapter for each data model class that you want to store in Hive. This adapter maps the fields in your data model to Hive boxes and makes it possible to store and retrieve instances of your data model.

6.Open a Hive box:

final myBox = await Hive.openBox('myBox');

Hive stores data in boxes. A box is a collection of key-value pairs, where the keys are strings and the values can be any data type that Hive supports. When you open a box, Hive loads the data from the box’s data file on disk (if it exists) and makes it available to your app.

7.Save data to a Hive box:

myBox.put('myKey', myData);

This saves myData to the box under the key ‘myKey’. You can save any data type that Hive supports.

8.Retrieve data from a Hive box:

final myData = myBox.get('myKey');

This retrieves the data from the box that is stored under the key ‘myKey’. If the key doesn’t exist, null is returned.

9.Listen for changes in a Hive box:

myBox.listenable().addListener(() {
// Handle box changes here
});

This sets up a listener that is called whenever the data in the box changes. You can use this to update your UI when the data changes.

10.Close a Hive box:

await myBox.close();

This closes the box and saves its data to the data file on disk. You should always close a box when you’re done using it.

11.Close Hive when your app exits:

await Hive.close();

This closes all open boxes and releases any resources that Hive is using. You should always close Hive when your app exits.

Code:

main.dart

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

import 'InfoScreen.dart';
import 'Model/person.dart';

main() async {
// Initialize hive
await Hive.initFlutter();
// Registering the adapter
Hive.registerAdapter(PersonAdapter());
// Opening the box
await Hive.openBox('peopleBox');

runApp(MyApp());
}

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
@override
void dispose() {
// Closes all Hive boxes
Hive.close();
super.dispose();
}

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hive Demo',
theme: ThemeData(
primarySwatch: Colors.indigo,
),
debugShowCheckedModeBanner: false,
home: const InfoScreen(),
);
}
}

Model/person.dart

import 'package:hive/hive.dart';

part 'person.g.dart';

@HiveType(typeId: 1)
class Person {
@HiveField(0)
final String? name;

@HiveField(1)
final String? fatherName;

@HiveField(2)
final String? motherName;

Person({
this.name,
this.fatherName,
this.motherName,
});
}

model/person.g.dart

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'person.dart';

// **************************************************************************
// TypeAdapterGenerator
// **
************************************************************************

class PersonAdapter extends TypeAdapter<Person> {
@override
final int typeId = 1;

@override
Person read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Person(
name: fields[0] as String?,
fatherName: fields[1] as String?,
motherName: fields[2] as String?,
);
}

@override
void write(BinaryWriter writer, Person obj) {
writer
..writeByte(3)
..writeByte(0)
..write(obj.name)
..writeByte(1)
..write(obj.fatherName)
..writeByte(2)
..write(obj.motherName);
}

@override
int get hashCode => typeId.hashCode;

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is PersonAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

personForm.dart

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';

import 'Model/person.dart';

class AddPersonForm extends StatefulWidget {
const AddPersonForm({Key? key}) : super(key: key);

@override
_AddPersonFormState createState() => _AddPersonFormState();
}

class _AddPersonFormState extends State<AddPersonForm> {
final _nameController = TextEditingController();
final _fatherNameController = TextEditingController();
final _motherNameController = TextEditingController();
final _personFormKey = GlobalKey<FormState>();

late final Box box;

String? _fieldValidator(String? value) {
if (value == null || value.isEmpty) {
return 'Field can\'t be empty';
}
return null;
}

// Add info to people box
_addInfo() async {
Person newPerson = Person(
name: _nameController.text,
fatherName: _fatherNameController.text,
motherName: _motherNameController.text,
);

box.add(newPerson);
print('Info added to box!');
}

@override
void initState() {
super.initState();
// Get reference to an already opened box
box = Hive.box('peopleBox');
}

@override
Widget build(BuildContext context) {
return Form(
key: _personFormKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Name'),
TextFormField(
controller: _nameController,
validator: _fieldValidator,
),
const SizedBox(height: 24.0),
const Text('Mother Name'),
TextFormField(
controller: _motherNameController,
validator: _fieldValidator,
),
const SizedBox(height: 24.0),
const Text('Father Name'),
TextFormField(
controller: _fatherNameController,
validator: _fieldValidator,
),
const Spacer(),
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 24.0),
child: SizedBox(
width: double.maxFinite,
height: 50,
child: ElevatedButton(
onPressed: () {
if (_personFormKey.currentState!.validate()) {
_addInfo();
Navigator.of(context).pop();
}
},
child: const Text('Add'),
),
),
),
],
),
);
}
}

addScreen.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'PersonForm.dart';

class AddScreen extends StatefulWidget {
const AddScreen({Key? key}) : super(key: key);

@override
State<AddScreen> createState() => _AddScreenState();
}

class _AddScreenState extends State<AddScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text('Add Info'),
),
body: const Padding(
padding: EdgeInsets.all(16.0)
,
child: AddPersonForm(),
),
);
}
}

infoScreen.dart

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

import 'AddScreen.dart';
import 'UpdateScreen.dart';

class InfoScreen extends StatefulWidget {
const InfoScreen({super.key});

@override
_InfoScreenState createState() => _InfoScreenState();
}

class _InfoScreenState extends State<InfoScreen> {
late final Box contactBox;

// Delete info from people box
_deleteInfo(int index) {
contactBox.deleteAt(index);

print('Item deleted from box at index: $index');
}

@override
void initState() {
super.initState();
// Get reference to an already opened box
contactBox = Hive.box('peopleBox');
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('People Info'),
),
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AddScreen(),
),
),
child: const Icon(Icons.add),
),
body: ValueListenableBuilder(
valueListenable: contactBox.listenable(),
builder: (context, Box box, widget) {
if (box.isEmpty) {
return const Center(
child: Text('Empty'),
);
}
else {
return ListView.builder(
itemCount: box.length,
itemBuilder: (context, index) {
var currentBox = box;
var personData = currentBox.getAt(index)!;
return InkWell(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => UpdateScreen(
index: index,
person: personData,
),
),
),
child: Card(
elevation: 2,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 8),
child: ListTile(
leading: CircleAvatar(
child: Text(
'${index + 1}',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
title: Text(personData.name),
subtitle: Text(
"Mother's name: ${personData.motherName}\nFather's name: ${personData.fatherName}",
style: const TextStyle(
fontSize: 14,
),
),
trailing: IconButton(
onPressed: () => _deleteInfo(index),
icon: const Icon(
Icons.delete,
color: Colors.red,
),
),
),
),
),
);
},
);



}
},
),
);
}
}

updatePersonForm.dart

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';

import 'Model/person.dart';

class UpdatePersonForm extends StatefulWidget {
final int index;
final Person person;

const UpdatePersonForm({
required this.index,
required this.person,
});

@override
_UpdatePersonFormState createState() => _UpdatePersonFormState();
}

class _UpdatePersonFormState extends State<UpdatePersonForm> {
final _personFormKey = GlobalKey<FormState>();

late final _nameController;
late final _motherNameController;
late final _fatherNameController;
late final Box box;

String? _fieldValidator(String? value) {
if (value == null || value.isEmpty) {
return 'Field can\'t be empty';
}
return null;
}

// Update info of people box
_updateInfo() {
Person newPerson = Person(
name: _nameController.text,
fatherName: _fatherNameController.text,
motherName: _motherNameController.text,
);

box.putAt(widget.index, newPerson);

print('Info updated in box!');
}

@override
void initState() {
super.initState();
// Get reference to an already opened box
box = Hive.box('peopleBox');
_nameController = TextEditingController(text: widget.person.name);
_fatherNameController = TextEditingController(text: widget.person.fatherName);
_motherNameController = TextEditingController(text: widget.person.motherName);
}

@override
Widget build(BuildContext context) {
return Form(
key: _personFormKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Name'),
TextFormField(
controller: _nameController,
validator: _fieldValidator,
),
const SizedBox(height: 24.0),
const Text('Mother Name'),
TextFormField(
controller: _motherNameController,
validator: _fieldValidator,
),
const SizedBox(height: 24.0),
const Text('father Name'),
TextFormField(
controller: _fatherNameController,
validator: _fieldValidator,
),
const Spacer(),
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 24.0),
child: SizedBox(
width: double.maxFinite,
height: 50,
child: ElevatedButton(
onPressed: () {
if (_personFormKey.currentState!.validate()) {
_updateInfo();
Navigator.of(context).pop();
}
},
child: const Text('Update'),
),
),
),
],
),
);
}
}

updateScreen.dart

import 'package:flutter/material.dart';

import 'Model/person.dart';
import 'UpdatePersonForm.dart';

class UpdateScreen extends StatefulWidget {
final int index;
final Person person;

const UpdateScreen({
required this.index,
required this.person,
});

@override
_UpdateScreenState createState() => _UpdateScreenState();
}

class _UpdateScreenState extends State<UpdateScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Update Info'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: UpdatePersonForm(
index: widget.index,
person: widget.person,
),
),
);
}
}

Output:






follow my Instagram account :


how to view stored data in Hive:

To view stored data in Hive, you can either use the Hive Visualizer or access the files directly in your app’s data directory.

1.Hive Visualizer:

1.Install the Hive Visualizer package by running the command “flutter pub global activate hive_visualizer” in your terminal.

2.Once the package is installed, run the command “flutter pub global run hive_visualizer” to start the visualizer.

3.In the visualizer, click on “Open Box” and select the box that you want to view data for.

4.You will now see all the data stored in the selected box.

2.Directly accessing the files:

1.Get the app’s data directory using the getApplicationDocumentsDirectory() function from the path_provider package.

2.In the data directory, you will find a folder named app_flutter. This is where Hive stores its files.

3.Inside the app_flutter folder, you will find a file for each box that you have created. The file name will be the name of the box with a .hive extension.

4.To view the contents of a file, you can use any text editor or SQLite browser that supports the Hive format.

5.Open the file using the text editor or SQLite browser to view the data stored in it.

Note: Directly accessing the files should be done with caution and only for debugging purposes. Editing the files directly can corrupt the data and cause unexpected behavior. It is recommended to use the Hive Visualizer to view and manage the data stored in Hive.

3.Android Studio’s Device File Explorer:

1.Open Android Studio and select the “View” menu from the toolbar.

2.Choose “Tool Windows” and then “Device File Explorer.”

3.Make sure your emulator or device is connected to Android Studio and visible in the “Device File Explorer” window.

4.In the Device File Explorer, navigate to the path you got (/data/user/0/com.example.hive_demo/app_flutter).

5.You should now see your data file(s) there.

Note: If you can’t find the “Device File Explorer” option in the “Tool Windows” menu, it might not be enabled. In that case, go to the “Settings/Preferences” menu, select “Plugins,” search for “Android Support,” and make sure the “Android Support” plugin is installed and enabled.


Post a Comment

0 Comments