Method to store data locally using a hive into

by SkillAiNest

In this tutorial, we will develop a fluttering application that shows how to create Crud (created, read, update, delete). Hive For local data storage.

The hive is a lightweight, sharp key value database written in a net dart. Unlike SQ Elite, it does not need a heavy SQL engine. It stores data in boxes, which you can think of containers (like tables, but easy).

For such a small crude app, the hives are a great fit because:

  1. This is offline first, and all data is stored locally on the device-internet.

  2. This type is safe and is well connected with dart models (as our Item,

  3. It is much faster than sqlite for easy tasks.

  4. It has a friendly API (hive_flutter) For things like reaction refreshments.

Hive is great for various use cases, such as storing app preferences/settings, small -to -medium -sized lists of structural data (such as notes, works, or purchase lists), offline catching for API response, and storing sessions or user profile data locally.

Here, hive items is strengthening a list like do/inventory, which means that everything (title, quantity) is stored locally and remains intact even after the app’s recovery.

By the end of this tutorial, you will have a fully active app that allows you to add, edit, delete items locally. I will provide clear explanations of the code along the way.

Table of contents:

  1. Provisions

  2. Step 1: Project Setup

  3. Step 2: Project folder structure

  4. Step 3: Application of application

  5. Screenshots

  6. Conclusion

Provisions

Before we start, make sure you have the following:

  1. SDK installed (version 3.0 or more recommended).

  2. Basic knowledge of the flurry: widgets, state/state lace widgets, and navigation.

  3. A code editor such as a VS code or Android studio.

  4. Familiar with dart classes, maps and inoms.

Step 1: Project Setup

Start by creating a new flurry project:

flutter create flutter_hive_crud
cd flutter_hive_crud

Open pubspec.yaml And add the following dependence:

dependencies:
  hive: ^2.2.3
  hive_flutter: ^1.1.0
  fluttertoast: ^8.2.12
  equatable: ^2.0.7

Install them:

flutter pub get
  • hive -Lightweight key value database for rash.

  • hive_flutter – Restrictions for the hive.

  • fluttertoast – Shows toast messages.

  • equatable – Easy to equate value in dart items.

Step 2: Project folder structure

Organize your project like this:

lib/
├── main.dart
├── model/
│   └── item.dart
├── controller/
│   └── controller.dart
├── constants/
│   ├── string_constants.dart
│   └── enums/
│       ├── status.dart
│       └── yes_no.dart
└── screens/
    ├── main_screen.dart
    └── widgets/
        ├── are_you_sure.dart
        ├── single_list_tile.dart
        ├── text_action.dart
        └── toast.dart

This structure is modular and able to maintain the app.

Step 3: Application of application

We will pass through the file through the file, and I will explain what each piece does when we go.

1. main.dart

This is an entry point of application. It initiates the hive and launches the app.

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'screens/main_screen.dart';
import 'constants/string_constants.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  
  await Hive.initFlutter();

  
  await Hive.openBox(StringConstants.hiveBox);

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Hive CRUD',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.brown),
        useMaterial3: true,
      ),
      home: const MainScreen(),
    );
  }
}

What is happening in this code is here:

  • WidgetsFlutterBinding.ensureInitialized() This ensures that the width widgets are ready.

  • Hive.initFlutter() Starts the hive in the clash.

  • Hive.openBox(...) Opens a permanent storage box.

  • MyApp Material theme and main screen sets.

2. item.dart (Model)

Since Hive Stores as a key value couple, we need to decide how to represent each item (such as entry or stock in the purchase list). We will keep your code organized, we will wrap each item in a dart class that will add to a dart class called Item. Thus, when we save the items in the hive, we can easily create, update, and change.

import 'package:equatable/equatable.dart';

class Item extends Equatable {
  final String title;
  final int quantity;

  const Item({required this.title, required this.quantity});

  @override
  List<Object> get props => (title, quantity);

  
  Map<String, dynamic> toMap() {
    return {'title': title, 'quantity': quantity};
  }

  
  factory Item.fromMap(Map<String, dynamic> map) {
    return Item(title: map('title'), quantity: map('quantity'));
  }
}

So whenever we save or bring data, we are just changing between Item (Class example) and Map (The shape of the hive)

What is happening here:

3. controller.dart (A hive on the hive)

This controller handles all HIVE CRUD operations and UI updates.

import 'package:flutter/material.dart';
import 'package:flutter_hive_crud/constants/string_constants.dart';
import 'package:flutter_hive_crud/screens/widgets/toast.dart';
import 'package:hive_flutter/hive_flutter.dart';
import '../constants/enums/status.dart';
import '../model/item.dart';

class HiveController {
  final BuildContext context;
  final Function fetchDataFunction;

  HiveController({required this.context, required this.fetchDataFunction});

  final hiveBox = Hive.box(StringConstants.hiveBox);

  
  List<Map<String, dynamic>> fetchData() {
    return hiveBox.keys.map((key) {
      final item = hiveBox.get(key);
      return {
        'key': key,
        'title': item('title'),
        'quantity': item('quantity'),
      };
    }).toList().reversed.toList();
  }

  Future<void> createItem({required Item item}) async {
    try {
      await hiveBox.add(item.toMap());
      afterAction('saved');
    } catch (e) {
      toastInfo(msg: 'Failed to create item', status: Status.error);
    }
  }

  Future<void> editItem({required Item item, required int itemKey}) async {
    try {
      hiveBox.put(itemKey, item.toMap());
      afterAction('edited');
    } catch (e) {
      toastInfo(msg: 'Failed to edit item', status: Status.error);
    }
  }

  Future<void> deleteItem({required int key}) async {
    try {
      await hiveBox.delete(key);
      afterAction('deleted');
    } catch (e) {
      toastInfo(msg: 'Failed to delete item', status: Status.error);
    }
  }

  Future<void> clearItems() async {
    try {
      await hiveBox.clear();
      afterAction('cleared');
    } catch (e) {
      toastInfo(msg: 'Failed to clear items', status: Status.error);
    }
  }

  void afterAction(String keyword) {
    toastInfo(msg: 'Item $keyword successfully', status: Status.success);
    fetchDataFunction(); 
    Navigator.of(context).pop(); 
  }
}

Let’s break it HiveController Through the code block, explaining every section and explaining why it is necessary.

Imports:

import 'package:flutter/material.dart';
import 'package:flutter_hive_crud/constants/string_constants.dart';
import 'package:flutter_hive_crud/screens/widgets/toast.dart';
import 'package:hive_flutter/hive_flutter.dart';
import '../constants/enums/status.dart';
import '../model/item.dart';

What is happening here:

  • flutter/material.dart – Provides material design widgets and utility.

  • string_constants.dart -AP contains a wide permanent name, for example the name of the hive box.

  • toast.dart – The usefulness of displaying toast messages for success or error feedback.

  • hive_flutter.dart – Integration of the package with a flurry.

  • status.dart – Types of status while representing Inum (error Or success) For toast messages.

  • item.dart – Model class that represents an individual (title + quantity).

These imports allow the controller to manage HIVE Data and interact with the UI.

Class Definition and Builder:

class HiveController {
  final BuildContext context;
  final Function fetchDataFunction;

  HiveController({required this.context, required this.fetchDataFunction});

What is happening here:

  • HiveController – This class manages all crore operations for the hive.

  • context – to flutter the current BuildContextModels or dialogues are used to navigate and show.

  • fetchDataFunction – A function approved by the UI that refreshes the list after performing any hive operation.

Constructor requires both parameters, ensuring that every instance HiveController UI has access to context and is a way to refresh data.

Hive Box Reference:

  final hiveBox = Hive.box(StringConstants.hiveBox);

Here,

  • hiveBox This is a reference to the hive box described in StringConstants.hiveBox.

  • A sixth box is like a key price store where we save our items locally.

  • This allows the controller to communicate with the hive every time the box is reopened.

Bring data:

  List<Map<String, dynamic>> fetchData() {
    return hiveBox.keys.map((key) {
      final item = hiveBox.get(key);
      return {
        'key': key,
        'title': item('title'),
        'quantity': item('quantity'),
      };
    }).toList().reversed.toList();
  }

What is this code doing: Here’s:

  • hiveBox.keys – Recover all the keys stored in the houses.

  • .map((key) => ...) – Repeat through each key and brings the item associated with it.

  • Each item transforms into a map that contains:

  • .toList().reversed.toList() – turns maps to a list and changes it The latest items appear before.

This method returns a list of items ready for display in UI.

Construction of an item:

  Future<void> createItem({required Item item}) async {
    try {
      await hiveBox.add(item.toMap());
      afterAction('saved');
    } catch (e) {
      toastInfo(msg: 'Failed to create item', status: Status.error);
    }
  }

In this code,

  • item.toMap() – changes Item Object to a map so that the hives can store it.

  • hiveBox.add(...) – Adds a new entry to the housewife, which automatically produces a unique key.

  • afterAction('saved') – Shows the toast of success, refreshes the UI, and closes any open modal.

  • catch The block handles mistakes and if something goes wrong, he shows the toast.

To edit an item:

  Future<void> editItem({required Item item, required int itemKey}) async {
    try {
      hiveBox.put(itemKey, item.toMap());
      afterAction('edited');
    } catch (e) {
      toastInfo(msg: 'Failed to edit item', status: Status.error);
    }
  }

In this code,

  • hiveBox.put(itemKey, item.toMap()) – Updates the item on a specified key with new data.

  • afterAction('edited') – Hands over feedback and UI updates.

  • catch The block handles any mistakes during the modification process.

Delete an item:

  Future<void> deleteItem({required int key}) async {
    try {
      await hiveBox.delete(key);
      afterAction('deleted');
    } catch (e) {
      toastInfo(msg: 'Failed to delete item', status: Status.error);
    }
  }

Here,

  • hiveBox.delete(key) – Removes the item associated with a specific key from the hive.

  • Calls afterAction('deleted') To refresh the UI and show a message of success.

  • Mistakes handle with toast.

Cleaning all items:

  Future<void> clearItems() async {
    try {
      await hiveBox.clear();
      afterAction('cleared');
    } catch (e) {
      toastInfo(msg: 'Failed to clear items', status: Status.error);
    }
  }

What is happening here:

  • hiveBox.clear() – delete All the items In the hive box

  • Useful for “clean” functionality in the app.

  • Success and mistakes are handled in the same way as other actions.

Wizard after action:

  void afterAction(String keyword) {
    toastInfo(msg: 'Item $keyword successfully', status: Status.success);
    fetchDataFunction(); 
    Navigator.of(context).pop(); 
  }

What is happening here:

  • toastInfo(...) – For example, success shows the toast, “The item has been successfully saved.”

  • fetchDataFunction() – Call UI -approved function to reload the list.

  • Navigator.of(context).pop() – An open modal or dialog (such as item form).

This method avoids repetition, centralizing the logic after any CRUD operation.

Summary of Hivecontroller’s Officials:

  1. Bring items from Hive for UI display.

  2. Create, update, delete and clean.

  3. Provide user feedback through toast messages.

  4. After any data changes, refresh the UI automatically.

  5. Administrate models and dialogues with context.

  6. HiveController Cleaner UI code summarized ceiling operations.

  7. Methods: createItemFor, for, for,. editItemFor, for, for,. deleteItemFor, for, for,. clearItems.

  8. afterAction Updates UI and shows success messages.

4. string_constants.dart

This string is a central storage for permanent names, such as the name of the hive box.

class StringConstants {
  static const hiveBox = 'items';
}

In this code:

  • class StringConstants – Defines a class that is used only to group permanent values ​​together.

  • static – This means you don’t have to create an example StringConstants To use it. You can directly access it StringConstants.hiveBox.

  • const -It makes time permanent, so it cannot be edited anywhere in your code.

  • 'items' – It’s just a wire price. In this case, it is the name of the hugging box that you will open.

5. status.dart (Enum)

enum Status { error, success }

In this code:

  • enum – For the short Counting. This is a special type that allows you to explain a fixed set of designated values.

  • Status – Name of Anum.

  • { error, success } – Possible values ​​that it can take.

So Status Now there is only one custom type Two correct values:

Status.error
Status.success

Why use it here?

Instead of passing through the sidewalks of plain wires "error" Or "success" (Which are easy to spell in invalid), can use the code Status.error Or Status.success.

For example, when showing toasts:

toastInfo(msg: 'Item deleted', status: Status.success);

Or ::

toastInfo(msg: 'Failed to delete item', status: Status.error);

This makes the code more secure (you can’t go through the error "sucess" And break things), clear (you can see the intention immediately), and ease to maintain (if you add more status later. warning Or infoIt’s just one place to update).

6. yes_no.dart (Enum)

enum YesNo { yes, no }

Why use it?

Instead of passing through the bolsters (true ).). false) Or strings ("yes" ).). "no"), You can use this anoma to make your intention more clear in the code.

For example:

YesNo userAccepted = YesNo.yes;

if (userAccepted == YesNo.yes) {
  print("User agreed!");
} else {
  print("User declined!");
}

It is more described by using a field bool Where you have to guess true Or false Meaning in context.

Common use cases:

  • Confirmation (for example, “Do you want to save this file?”,

  • Settings Toggle (for example, “Enable notifications?”,

  • API answers that return "yes" ).). "no" You can make them a map of this inom for a safe handling as a wire.

7. toast.dart

import 'package:fluttertoast/fluttertoast.dart';
import '../../../constants/enums/status.dart';

void toastInfo({required String msg, required Status status}) {
  Fluttertoast.showToast(
    msg: msg,
    backgroundColor: status == Status.error ? Colors.red : Colors.green,
    toastLength: Toast.LENGTH_LONG,
    gravity: ToastGravity.TOP,
  );
}

This is a helpful function to display toast messages in your fluttering app.

A Toast There is a small, temporary popup message (usually below the screen or top) to inform the user about something immediately. For example, you may have “Item successfully saved” Or “Error to delete the item”.

8. are_you_sure.dart (Confirmation dialog)

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

Future<void> areYouSureDialog({
  required String title,
  required String content,
  required BuildContext context,
  required Function action,
  bool isKeyInvolved = false,
  int key = 0,
}) {
  return showDialog(
    context: context,
    builder: (context) => Platform.isIOS
        ? CupertinoAlertDialog(
            title: Text(title),
            content: Text(content),
            actions: (
              CupertinoDialogAction(
                  onPressed: () =>
                      isKeyInvolved ? action(key: key) : action(),
                  child: const Text('Yes')),
              CupertinoDialogAction(
                  onPressed: () => Navigator.of(context).pop(),
                  child: const Text('Dismiss')),
            ),
          )
        : AlertDialog(
            title: Text(title),
            content: Text(content),
            actions: (
              ElevatedButton(
                  onPressed: () =>
                      isKeyInvolved ? action(key: key) : action(),
                  child: const Text('Yes')),
              ElevatedButton(
                  onPressed: () => Navigator.of(context).pop(),
                  child: const Text('Dismiss')),
            ),
          ),
  );
}

This code handles the user’s confirmation for actions such as deletion or clear.

This function shows the verified dialog from the platform (Are you sure?) They:

  1. works with one on iOS CupertinoAlertDialog.

  2. Works on Android/others with a content AlertDialog.

  3. A provided calls provided action When the user presses yes.

  4. When the user is suppressed, the dialogue closes.

  5. Optionally passes a key In the action function.

9. single_list_tile.dart (List Item Waget)

import 'package:flutter/material.dart';
import '../../model/item.dart';
import 'text_action.dart';
import '../../constants/enums/yes_no.dart';

class SingleListItem extends StatelessWidget {
  final Item item;
  final int itemKey;
  final Function editHandle;
  final Function deleteDialog;
  final Function deleteItem;

  const SingleListItem({
    super.key,
    required this.item,
    required this.itemKey,
    required this.editHandle,
    required this.deleteDialog,
    required this.deleteItem,
  });

  @override
  Widget build(BuildContext context) {
    return Dismissible(
      key: ValueKey(itemKey),
      confirmDismiss: (_) => showDialog(
        context: context,
        builder: (_) => AlertDialog(
          title: const Text('Are you sure?'),
          content: Text('Delete ${item.title}?'),
          actions: (
            textAction('Yes', YesNo.yes, context),
            textAction('No', YesNo.no, context),
          ),
        ),
      ),
      onDismissed: (_) => deleteItem(key: itemKey),
      background: Container(
        color: Colors.red,
        alignment: Alignment.centerRight,
        padding: const EdgeInsets.only(right: 20),
        child: const Icon(Icons.delete, color: Colors.white),
      ),
      child: ListTile(
        title: Text(item.title),
        subtitle: Text(item.quantity.toString()),
        trailing: Row(
          mainAxisSize: MainAxisSize.min,
          children: (
            IconButton(onPressed: () => editHandle(item: item, key: itemKey), icon: const Icon(Icons.edit)),
            IconButton(onPressed: () => deleteDialog(key: itemKey), icon: const Icon(Icons.delete)),
          ),
        ),
      ),
    );
  }
}

This code represents each list item that has edited/deleting options and swipe -to -delete functionality.

It represents the widget An item (Like a shopping list, Todo List, Inventory app, and a row like that):

  1. Swipe -to -delete functionality.

  2. Edit and delete the buttons.

  3. A confirmation dialogue before dismissal

10. main_screen.dart (UI + State Management)

This is the main screen that puts everything together, including forms, lists and models.
Due to the length, the entire explanation is already well developed in the original code, which is covered:

  • itemModal() – Sheet form below for creation/editing.

  • fetchData() – Load the items from the hive.

  • editHandle() – Load the item for editing.

  • deleteDialog() – Confirm deletion.

  • clearAllDialog() – Confirm all items cleaned.

Screenshots

Screenshot of a population list

Screenshot to add a new item

The dialog screenshot is asking to confirm whether you want to delete an item in iOS

Screenshot of Deleting Dialogue Box in Android

Screenshot of the Dialog Box to Clear Items

Toast notification screenshot

An empty condition screenshot.

Conclusion

Now you have a fully active fluttering app with Hive for local data perseverance. May your app:

  • Create, read, update, delete.

  • Show toast messages for feedback.

  • Confirm actions with the Android and iOS dialogue.

  • Clean, modular architecture with controllers, models, and widgets.

You can find the hive more Hive package documents If you want to get more information.

You may also like

Leave a Comment

At Skillainest, we believe the future belongs to those who embrace AI, upgrade their skills, and stay ahead of the curve.

Get latest news

Subscribe my Newsletter for new blog posts, tips & new photos. Let's stay updated!

@2025 Skillainest.Designed and Developed by Pro