Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The box "contacts" is already open and of type Box<Contact> when trying to access Hive database in flutter

I initialized box database in main as follow

void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    final appDocumentDirectory = await path_provider.getApplicationDocumentsDirectory();
    Hive.init(appDocumentDirectory.path);
    Hive.registerAdapter(ContactAdapter());
    runApp(MyApp());
}

then I open box in the material app by using FutureBuilder plugin as follows:

  FutureBuilder(
      future: Hive.openBox<Contact>('contacts'),
      builder: (context, snapshot) {
        if(snapshot.connectionState == ConnectionState.done){
          if(snapshot.hasError){
            return Text(snapshot.error.toString() );
          }
          return ContactPage();
        } else {
          return Scaffold();
        }
      }
    ),

and inside ContactPage()

I create this:-

  ValueListenableBuilder(
                valueListenable: Hive.box<Contact>('contacts').listenable(),
                builder: (context,Box<Contact> box,_){
                  if(box.values.isEmpty){
                    return Text('data is empty');
                  } else {
                    return ListView.builder(
                      itemCount: box.values.length,
                      itemBuilder: (context,index){
                        var contact = box.getAt(index);
                        return ListTile(
                          title: Text(contact.name),
                          subtitle: Text(contact.age.toString()),
                        );
                      },
                    );
                  }
                },
               )

when I run the application I get the following error

The following HiveError was thrown while handling a gesture:
The box "contacts" is already open and of type Box<Contact>.

and when I tried to use the box without opening it, I got error mean the box is not open.

Do I have to use box without opening it inside ValueListenableBuilder? But then I have to open same box again in the different widget to add data on it.

like image 392
aboodrak Avatar asked Feb 17 '20 06:02

aboodrak


People also ask

How do I write to hive box in flutter?

Writing to Box is like writing to Map <key, value>. All keys must be ASCII strings with a maximum length of 255 characters or unsigned 32-bit integers. One advantage of Hive is that updates are instantaneous without the use of async in Flutter, and if you want to be sure to get data, you can add the await of the Future class.

How do I Close a box in hive?

Before your application exits, you should call Hive.close () to close all open boxes. Don’t worry if the app is killed before you close Hive, it doesn’t matter. With the Box opened, let's add a new contact to the database after we submit the form.

How to use a box in flutter?

To use a Box, you must open the Box to use it. This method is extremely useful in Flutter because it can be called anywhere without having to pass between widgets. But if Box is already open, the above code will be disabled and the internal parameters will be ignored. Once opened Box can proceed to Read, Write, Delete the elements in it.

What is watchboxbuilder in hive_flutter?

While the core hive package can run on just about any Dart platform, hive_flutter adds a WatchBoxBuilder widget to simplify the UI development a bit by not having to use the StreamBuilder together with all its boilerplate. Now, we can effortlessly update the UI whenever any change happens inside the contactsBox.


2 Answers

I'm jumping on this thread because I had a hard time trying to figure out how to deal with the deprecated WatchBoxBuilder while using the resocoder's Hive tutorial, and a google search led me here.

This is what I ended up using:

main.dart:

void main() async {
  if (!kIsWeb) { // <-- I put this here so that I could use Hive in Flutter Web
    final dynamic appDocumentDirectory =
        await path_provider.getApplicationDocumentsDirectory();
    Hive.init(appDocumentDirectory.path as String);
  }
  Hive.registerAdapter(ContactAdapter());

  runApp(child: MyApp());
}

and then ContactPage() (note: it's the same as OP's):

Widget _buildListView() {
  return ValueListenableBuilder(
    valueListenable: Hive.box<Contact>('contacts').listenable(),
    builder: (context, Box<Contact> box, _) {
      if (box.values.isEmpty) {
        return Text('data is empty');
      } else {
        return ListView.builder(
          itemCount: box.values.length,
          itemBuilder: (context, index) {
            var contact = box.getAt(index);
            return ListTile(
              title: Text(contact.name),
              subtitle: Text(contact.age.toString()),
            );
          },
        );
      }
    },
  );
}
like image 106
William Terrill Avatar answered Nov 15 '22 06:11

William Terrill


Its a simple explanation actually:
1. It only occurs when your box has a generic type like
Hive.openBox<User>('users')

2. So once you call Hive.box('users') without specifying the generic type this error occurs.

THATS EVERYTHING.

SOLUTION
Hive.box<User>('users') at each call :)

like image 29
Ray Zion Avatar answered Nov 15 '22 06:11

Ray Zion