8

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.

padaleiana
  • 955
  • 1
  • 14
  • 23
aboodrak
  • 873
  • 9
  • 15

4 Answers4

5

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 :)

Ray Zion
  • 610
  • 10
  • 11
1

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()),
            );
          },
        );
      }
    },
  );
}
William Terrill
  • 3,484
  • 4
  • 31
  • 41
0

It is probably because you are trying to open the box inside FutureBuilder. If somehow it tries to rebuild itself, it will try to open the box which is already opened. Can you try to open the box after you register the adapter like:

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

And instead of FutureBuilder just return ContactPage

Selim Kundakçıoğlu
  • 1,986
  • 10
  • 20
0

In main.dart file :

future: Hive.openBox('contacts'),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.hasError) {
            return Text(snapshot.error.toString());
          } else {
            return ContactPage();
          }
        } else {
          return Center(
            child: CircularProgressIndicator(),
          );
        }
      },

In ContactPage:

return WatchBoxBuilder(
box: Hive.box('contacts'),
builder: (context, contactBox) {
  return ListView.builder(
    itemCount: contactBox.length,
    itemBuilder: (context, index) {
      final contact = contactBox.getAt(index) as Contact;
      return ListTile(
        title: Text(contact.name),
        subtitle: Text(contact.number),
        trailing: Row(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            IconButton(
              icon: Icon(Icons.refresh),
              onPressed: () {
                contactBox.putAt(
                  index,
                  Contact('${contact.name}*', contact.number),
                );
              },
            ),
            IconButton(
              icon: Icon(Icons.delete),
              onPressed: () {
                contactBox.deleteAt(index);
              },
            ),
          ],
        ),
      );
    },
  );
},

);

It's OK to open the box in future call..

Mhamza007
  • 151
  • 1
  • 4