【问题标题】:The box "contacts" is already open and of type Box<Contact> when trying to access Hive database in flutter尝试在 Flutter 中访问 Hive 数据库时,“联系人”框已打开且类型为 Box<Contact>
【发布时间】:2020-06-01 01:51:36
【问题描述】:

我在 main 中初始化了 box 数据库,如下所示

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

然后我使用 FutureBuilder 插件在材料应用程序中打开框,如下所示:

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

在 ContactPage() 内部

我创建了这个:-

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

当我运行应用程序时,我收到以下错误

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

当我尝试在不打开盒子的情况下使用盒子时,我收到错误提示盒子没有打开。

我必须使用盒子而不在 ValueListenableBuilder 中打开它吗? 但是我必须在不同的小部件中再次打开同一个框才能在其上添加数据。

【问题讨论】:

    标签: database flutter flutter-hive


    【解决方案1】:

    我跳上这个线程是因为我在使用 resocoder 的 Hive 教程时很难弄清楚如何处理已弃用的 WatchBoxBuilder,而谷歌搜索将我带到了这里。

    这是我最终使用的:

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

    然后是 ContactPage() (注意:它与 OP 相同):

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

    【讨论】:

      【解决方案2】:

      这可能是因为您试图打开FutureBuilder 中的盒子。如果它试图重建自己,它会尝试打开已经打开的盒子。注册适配器后可以尝试打开盒子吗:

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

      而不是FutureBuilder,只需返回ContactPage

      【讨论】:

        【解决方案3】:

        在 main.dart 文件中:

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

        在联系人页面中:

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

        );

        以后打电话开箱就OK了..

        【讨论】:

        • 请注意,WatchBoxBuilder 已被弃用,取而代之的是 ValueListenableBuilder。
        【解决方案4】:

        其实是一个简单的解释:
        1. 仅当您的盒子具有通用类型时才会发生
        Hive.openBox&lt;User&gt;('users')

        2. 因此,一旦您调用 Hive.box('users') 而不指定泛型类型,就会发生此错误。

        这就是一切

        解决方案
        每次通话时Hive.box&lt;User&gt;('users') :)

        【讨论】:

          猜你喜欢
          • 2020-12-18
          • 1970-01-01
          • 2021-07-21
          • 1970-01-01
          • 2015-07-29
          • 2022-11-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多