Search code examples
flutterdartflutter-hive

Flutter Hive update issue


I created a basic app for creating, deleting, updating, and reading employee details using Hive in Flutter and update function is not working. I am passing the object of class through the update function but it's not working and I am using a list of model to store data.

This is code for the hive controller:

import 'package:hive_demo/model/emplyee_model.dart';
import 'package:hive_flutter/hive_flutter.dart';

class EmployeeController {
  static List<EmployeeModel> employeeList = [];

  var box = Hive.box('db');

  void initData() {
    employeeList = [
      EmployeeModel(name: 'name', designation: 'designation'),
    ];
  }

  void adddata(EmployeeModel employeeModel) async {
    employeeList.add(employeeModel);
    await box.put('employeedb', employeeList);
  }

  void getData() {
    List demoList = box.get('employeedb');
    employeeList = demoList
        .map((e) => EmployeeModel(name: e.name, designation: e.designation))
        .toList();
  }

  void deletedata(int index) async {
    employeeList.removeAt(index);
    await box.put('employeedb', employeeList);
  }

  void updateData(int id, EmployeeModel employeeModel) async {
    await box.putAt(id, employeeModel);

    getData();
  }
}

This is code of home page:

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_demo/controller/employee_controller.dart';
import 'package:hive_demo/model/emplyee_model.dart';

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

  @override
  State<Homepage> createState() => _HomepageState();
}

class _HomepageState extends State<Homepage> {
  TextEditingController nametextcontroller = TextEditingController();
  TextEditingController designationtextcontroller = TextEditingController();
  EmployeeController employeeController = EmployeeController();

  var box = Hive.box('db');

  @override
  void initState() {
    if (box.isNotEmpty) {
      employeeController.getData();
    } else {
      employeeController.initData();
    }

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            TextField(
              controller: nametextcontroller,
              decoration: const InputDecoration(
                  border: OutlineInputBorder(), hintText: 'name'),
            ),
            const SizedBox(
              height: 10,
            ),
            TextField(
              controller: designationtextcontroller,
              decoration: const InputDecoration(
                  border: OutlineInputBorder(), hintText: 'designation'),
            ),
            ElevatedButton(
                onPressed: () {
                  employeeController.adddata(EmployeeModel(
                      name: nametextcontroller.text,
                      designation: designationtextcontroller.text));
                  setState(() {});
                },
                child: const Text('Add')),
            Expanded(
              child: ListView.separated(
                  //list tile
                  itemBuilder: (context, index) => ListTile(
                        title:
                            Text(EmployeeController.employeeList[index].name),
                        subtitle: Text(
                            EmployeeController.employeeList[index].designation),
                        trailing: Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            IconButton(
                                onPressed: () {
                                  nametextcontroller.text = EmployeeController
                                      .employeeList[index].name;
                                  designationtextcontroller.text =
                                      EmployeeController
                                          .employeeList[index].designation;
                                },
                                icon: const Icon(Icons.edit)),
                            IconButton(
                                onPressed: () {
                                  employeeController.deletedata(index);
                                  setState(() {});
                                },
                                icon: const Icon(
                                  Icons.delete,
                                  color: Colors.red,
                                )),
                            IconButton(
                                onPressed: () {
                                  employeeController.updateData(
                                      index,
                                      EmployeeModel(
                                          name: nametextcontroller.text,
                                          designation:
                                              designationtextcontroller.text));

                                  setState(() {});
                                },
                                icon: const Icon(Icons.refresh)),
                          ],
                        ),
                      ),
                  separatorBuilder: (context, index) => const Divider(
                        height: 9,
                      ),
                  itemCount: EmployeeController.employeeList.length),
            )
          ],
        ),
      ),
    );
  }
}

How can I solve it?


Solution

  • Hive it's a very fast database, and it's main purpose is to manage key/value data, however you can handle objects using TypeAdapters maybe you have this definition in other file, but I can't see it in the code shared.

    Anyways, I would check for two common mistakes when using Hive:

    1. Confirm the box is open: Hive.openBox('db'); You need to add the openBox before var box = Hive.box('db');
    2. If you want to handle objects instead of key/values, you have to register a TypeAdapter which converts the object from and to binary form. There is a good example in the documentation page.

    What I usually do is to create a class to initiate Hive. I call it "LocalStorageService":

    import 'package:hive_flutter/hive_flutter.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:hive_demo/model/employee_model.dart';
    
    class LocalStorageService {
    
        static Future<void> initLocalStorage() async {
            try {
                var dir = await getApplicationDocumentsDirectory();
                await Hive.initFlutter(dir.path);
                Hive.registerAdapter(EmployeeAdapter());
                
                await Hive.openBox('db');
                //initDefaults(); 
    
            } catch (e) {
                debugPrint("ERROR ON initLocalStorage(): ${e.toString()}");
            }
        }
    
        static void initDefaults() {
          // I use this function to run some validations and set default values
        }
    }
    

    And I call the initLocalStorage() method from the LocalStorageService class in my main.dart file:

    void main() async {
        WidgetsFlutterBinding.ensureInitialized();    
        await LocalStorageService.initLocalStorage();
    
        runApp(MyApp());
    
    }