Logo

dev-resources.site

for different kinds of informations.

Flutter Hive: Mastering Offline Data Storage in Flutter

Published at
2/4/2024
Categories
flutter
tutorial
database
mobile
Author
Gosu Code
Categories
4 categories in total
flutter
open
tutorial
open
database
open
mobile
open
Flutter Hive: Mastering Offline Data Storage in Flutter

Introduction

Flutter Hive is not just a database; it's your app's secret weapon for storing data faster than you can say "hot reload." Hive is a lightweight, NoSQL database designed for Flutter, and it's here to make your offline experience smoother than ever.

Unleashing the Hive Magic

📦 Boxes for Everything:

Hive organizes data neatly into 'boxes.' Think of them as magical containers where your app's data resides, ready to be accessed at the speed of thought.

🔍 Query Like a Pro:

Searching for data? Hive's got your back. Its querying capabilities make finding information a breeze, ensuring you get what you need when you need it.

Flutter + Hive = 💙

When Flutter and Hive join forces, your app becomes an offline superstar. No more worries about lost connections or slow data access - Hive's got your back, keeping your app running smoothly, online or offline.

Let's Dive In!

Ready to embrace the speed, simplicity, and Flutter-friendliness of Hive? Buckle up as we dive into the world of Flutter Hive - your ticket to lightning-fast offline storage! 🚀

1. Installing dependencies
Add these dependencies on your pubspec.yaml

dependencies:
  hive: ^2.2.3
  hive_flutter: ^1.1.0

dev_dependencies:
  hive_generator: ^1.1.3
  build_runner: ^2.1.11

Run the following command on your terminal to install dependencies.

flutter pub get
flutter pub add hive hive_flutter hive_generator build_runner

2. Initializing

main.dart

// Setting up Hive in Flutter
import 'package:hive/hive.dart';

void main() async {
  await Hive.initFlutter();
  // Hive is now ready to roll!
runApp(const MyApp());
}

3. Create Model
person_model.dart

import 'package:hive/hive.dart';

part 'person_model.g.dart';

@HiveType(typeId: 1) //typeId should be unique for each model
class PersonModel {
  @HiveField(0) //uinque id for each field
  String name;

  @HiveField(1)
  int age;

  @HiveField(2)
  List<Person> friends;
}

4. Generate TypeAdapter
After writing creating model, run the following command to generate TypeAdapter

dart run build_runner build

Add the generated TypeAdapter to the main.dart file.

import 'package:hive/hive.dart';

void main() async {
  await Hive.initFlutter();
  Hive.registerAdapter(PersonModelAdapter()); //add TypeAdapater
runApp(const MyApp());
}

5. Creating a CRUD service
Now we need to create some function to perform CRUD(create, read, update, delete) operation.

Let's create another file service.dart where we will keep our CRUD functions.

import 'package:your_app/models/person_model.dart';
import 'package:hive_flutter/hive_flutter.dart';

class Service {
final String  _boxName = "personBox";

Future<Box<PersonModel>> get _box async =>
      await Hive.openBox<PersonModel>(_boxName);

//create
  Future<void> addPerson(PersonModel personModel) async {
    var box = await _box;
    await box.add(personModel);
  }

//read
  Future<List<PersonModel>> getAllPerson() async {
    var box = await _box;
    return box.values.toList();
  }

//update
  Future<void> updateDeck(int index, PersonModel personModel) async { 
    var box = await _box;
    await box.putAt(index, personModel);
  }

//delete
  Future<void> deletePerson(int index) async {
    var box = await _box;
    await box.deleteAt(index);
  }
}

Now we can use these function to perform CRUD operation.

6. Implementing

Adding to the box

final PersonService _personService = PersonService();
TextEditingController nameController = TextEditingController();
TextEditingController ageController = TextEditingController();

//create a function to add the data
 void saveAndPop(BuildContext context) async{
    Navigator.pop(context);
    String name = nameController.text.trim();
    int age = nameController.text
    var person = CardModel(person: name, age: age);
    await _personService.addPerson(person);           //writing
  }

..// rest of your code

Column(
          children: [
            TextField(
              controller: nameController,
              decoration: const InputDecoration(
                hintText: 'Name'
              ),
            ),
            TextField(
              controller: ageController,
              decoration: const InputDecoration(
                hintText: 'Age'
              ),
            ),
            ElevatedButton(onPressed: (){
              saveAndPop(context);
            }, child: Text("Add")),
            ElevatedButton(onPressed: (){
              Navigator.pop(context);
            }, child: Text("Cancel")),
          ],
        ),

Getting from the box

//create an instance of the PersonService class.
final PersonService _personService = PersonService();

//open the box
Future<void> openBox() async {
  await Hive.openBox<PersonModel>('personBox');
}

@override
void initState() {    //calls when the widget is created
  super.initState();
  openBox();
}

@override
Widget build(BuildContext context) {
return Scaffold(
      body:
        //asynchronously build a widget tree
        FutureBuilder(
          future: _personService.getAllPerson(),
          builder: ( (context, snapshot) {
            if(snapshot.connectionState == ConnectionState.done){
              return 
           ValueListenableBuilder(
            //listens to changes in the hive box
            valueListenable: Hive.box<PersonModel>('personBox').listenable(), 
            builder: (context, box, _){
              //checking if the box is empty
              if(box.values.isEmpty){
              return const Center(
                child: Center(child: Text("No person available.")),
              );
              }
              //returns the data in list if there are any
              return ListView.builder(
                itemCount: box.values.length,
                itemBuilder: (context, index){
                  //retrieving PersonModel object from the box
                  var person = box.getAt(index);
                  return Column(
                           children: [
                              //displaying info
                              Text(person!.name),
                              Text(person!.age),
                              Text("Add Person"),
                            ],
                          );
                        }
                      );
                    });
                } else {
                 //if the future is not complete
                return Center(
                 child: CircularProgressIndicator()
              );
          }
      })
    )
  );
}

Deleting from the box

IconButton(
       onPressed: (){
         _cardService.deleteCard(index);
         }, icon: Icon(
        Icons.delete, 
       ))

Updating the values

final PersonService _personService = PersonService();

  TextEditingController nameController = TextEditingController();
  TextEditingController ageController = TextEditingController();

  //function to update
  void saveAndPop(BuildContext context) async{
    Navigator.pop(context);
    String name = nameController.text.trim();
    String age = ageController.text.trim();

    var card = PersonModel(name: name, age: age);
    await _personService.updatePerson(index,card);
  }

//Display the name and age before the change
  @override
  void initState(){
    super.initState();
    nameController.text = widget.name;
    ageController.text = widget.age;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
          children: [
            TextField(
              controller: nameController,
              decoration: const InputDecoration(
                hintText: 'Name'
              ),
            ),
            TextField(
              controller: ageController,
              decoration: const InputDecoration(
                hintText: 'Age'
              ),
            ),
            ElevatedButton(onPressed: (){
              saveAndPop(context);
            }, child: Text("Update")),
          ],
        ),
    );
  }

Thank you for investing your time in understanding how Flutter Hive can transform your applications. If you found value in this blog or if there's anything you think I missed, please don't hesitate to drop your thoughts in the comments below. Your feedback is immensely valuable, and I encourage you to share your insights, ask questions, or point out any mistakes you may have notices.

Featured ones: