i got this error when i tried to access Hive database in flutter The box “contacts” is already open and of type Box<Contact>

懵懂的女人 提交于 2020-07-21 07:51:40

问题


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 follow

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


回答1:


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..




回答2:


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




回答3:


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()),
            );
          },
        );
      }
    },
  );
}


来源:https://stackoverflow.com/questions/60257233/i-got-this-error-when-i-tried-to-access-hive-database-in-flutter-the-box-contac

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!