如何解决 Box not Found 错误 Hive Flutter

Posted

技术标签:

【中文标题】如何解决 Box not Found 错误 Hive Flutter【英文标题】:How to solve the Box not Found error Hive Flutter 【发布时间】:2021-03-04 18:51:43 【问题描述】:

我有一个主屏幕,我在其中创建了一个 4 导航屏幕,所以当用户输入登录 ID 和密码时,它会调用主屏幕。但是当用户第一次导航到主屏幕时,它显示 Box 未初始化,但是当我点击底部导航栏时,它显示了列表,但我想显示列表,即使用户先登录。

这是我的错误:

这是用户登录时的主屏幕代码:

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart';
import 'package:secret_keeper/Database/Hive/BankModel.dart';
import 'package:secret_keeper/Database/Hive/CardModel.dart';
import 'package:secret_keeper/Database/Hive/NotesModel.dart';
import 'package:secret_keeper/Database/Hive/PasswordModel.dart';
import 'package:secret_keeper/screens/home_screen/banks/BanksNavigation.dart';
import 'package:secret_keeper/screens/home_screen/cards/CardsNavigation.dart';
import 'package:secret_keeper/screens/home_screen/notes/NotesNavigation.dart';
import 'package:secret_keeper/screens/home_screen/passwords/PasswordsNavigation.dart';
import 'package:secret_keeper/screens/input_screen/bank_input/BankInput.dart';
import 'package:secret_keeper/screens/input_screen/card_input/CardInput.dart';
import 'package:secret_keeper/screens/input_screen/note_input/NoteInput.dart';
import 'package:secret_keeper/screens/input_screen/password_input/PasswordInput.dart';

Box passwordBox, cardBox, bankBox, notesBox;

class Home extends StatefulWidget 
  @override
  _HomeState createState() => _HomeState();


class _HomeState extends State<Home> 
  //Properties

  int currentTab = 0;
  final List<Widget> screens = [
    PasswordsNavigation(),
    CardsNavigation(),
    BanksNavigation(),
    NotesNavigation(),
  ];

  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    Hive.registerAdapter(PasswordModelAdapter());
    Hive.registerAdapter(CardModelAdapter());
    Hive.registerAdapter(BankModelAdapter());
    Hive.registerAdapter(NotesModelAdapter());
    _openBox();
  

  Future _openBox() async 
    WidgetsFlutterBinding.ensureInitialized();
    var dir = await getApplicationDocumentsDirectory();
    Hive.init(dir.path);
    passwordBox = await Hive.openBox<PasswordModel>('passwordBox');
    cardBox = await Hive.openBox<CardModel>('cardBox');
    bankBox = await Hive.openBox<BankModel>('bankBox');
    notesBox = await Hive.openBox<NotesModel>('notesBox');
    return;
  

  //Active Page (Tab)

  Widget currentScreen = PasswordsNavigation();
  final PageStorageBucket bucket = PageStorageBucket();
  Icon cusIcon = Icon(Icons.search);
  Widget cusSearchBar = Row(children: [
    Text(
      "SECRET",
      style: TextStyle(color: Colors.orange[900], fontWeight: FontWeight.w700),
    ),
    Text(
      "KEEPER",
      style: TextStyle(color: Colors.black87, fontWeight: FontWeight.w700),
    ),
  ]);

  void checkNavigation()
    if(currentTab == 0)
      Navigator.push(context, MaterialPageRoute(builder: (context) => PasswordInput()));
    else if(currentTab == 1)
      Navigator.push(context, MaterialPageRoute(builder: (context) => CardInput()));
    else if(currentTab == 2)
      Navigator.push(context, MaterialPageRoute(builder: (context) => BankInput()));
    else
      Navigator.push(context, MaterialPageRoute(builder: (context) => NoteInput()));
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: cusSearchBar,
        actions: [
          IconButton(
            onPressed: () 
              setState(() 
                if (this.cusIcon.icon == Icons.search) 
                  this.cusIcon = Icon(Icons.cancel, color: Colors.black87);
                  this.cusSearchBar = Container(
                    height: 50,
                    child: TextField(
                      textInputAction: TextInputAction.go,
                      autofocus: true,
                      decoration: InputDecoration(
                          border: InputBorder.none, hintText: "Search here"),
                      style: TextStyle(
                        fontSize: 20.0,
                      ),
                    ),
                  );
                 else 
                  this.cusIcon = Icon(Icons.search);
                  this.cusSearchBar = Row(children: [
                    Text(
                      "SECRET",
                      style: TextStyle(
                          color: Colors.orange[900],
                          fontWeight: FontWeight.w700),
                    ),
                    Text(
                      "KEEPER",
                      style: TextStyle(
                          color: Colors.black87, fontWeight: FontWeight.w700),
                    ),
                  ]);
                
              );
            ,
            icon: cusIcon,
          ),
          IconButton(
            onPressed: () ,
            icon: Icon(Icons.more_vert),
          ),
        ],
      ),
      body: PageStorage(
        child: currentScreen,
        bucket: bucket,
      ),

      //FAB Button

      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        backgroundColor: Colors.orangeAccent,
        onPressed: () 
          checkNavigation();
        ,
      ),

      //FAB Position

      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,

      //Bottom App Bar

      bottomNavigationBar: BottomAppBar(
        shape: CircularNotchedRectangle(),
        child: Container(
          height: 60,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Row(
                children: [
                  MaterialButton(
                    minWidth: 40,
                    onPressed: () 
                      setState(() 
                        currentScreen = PasswordsNavigation();
                        currentTab = 0;
                      );
                    ,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.paste_sharp,
                          color: currentTab == 0 ? Colors.orange : Colors.grey,
                        ),
                        Text(
                          'Passwords',
                          style: TextStyle(
                            color:
                                currentTab == 0 ? Colors.orange : Colors.grey,
                          ),
                        ),
                      ],
                    ),
                  ),
                  MaterialButton(
                    minWidth: 40,
                    onPressed: () 
                      setState(() 
                        currentScreen = CardsNavigation();
                        currentTab = 1;
                      );
                    ,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.credit_card_rounded,
                          color: currentTab == 1 ? Colors.orange : Colors.grey,
                        ),
                        Text(
                          'Cards',
                          style: TextStyle(
                            color:
                                currentTab == 1 ? Colors.orange : Colors.grey,
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
              Row(
                children: [
                  MaterialButton(
                    minWidth: 40,
                    onPressed: () 
                      setState(() 
                        currentScreen = BanksNavigation();
                        currentTab = 2;
                      );
                    ,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.food_bank_outlined,
                          color: currentTab == 2 ? Colors.orange : Colors.grey,
                        ),
                        Text(
                          'Banks',
                          style: TextStyle(
                            color:
                                currentTab == 2 ? Colors.orange : Colors.grey,
                          ),
                        ),
                      ],
                    ),
                  ),
                  MaterialButton(
                    minWidth: 40,
                    onPressed: () 
                      setState(() 
                        currentScreen = NotesNavigation();
                        currentTab = 3;
                      );
                    ,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.notes,
                          color: currentTab == 3 ? Colors.orange : Colors.grey,
                        ),
                        Text(
                          'Notes',
                          style: TextStyle(
                            color:
                                currentTab == 3 ? Colors.orange : Colors.grey,
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  

这是我要显示列表的第一个导航屏幕代码:

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:secret_keeper/Database/Hive/PasswordModel.dart';
import 'package:secret_keeper/screens/home_screen/Home.dart';

class PasswordsNavigation extends StatefulWidget 
  @override
  _PasswordsNavigationState createState() => _PasswordsNavigationState();


class _PasswordsNavigationState extends State<PasswordsNavigation> 
  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    // Hive.registerAdapter(PasswordModelAdapter());
    _openBox();
  

  Future _openBox() async 
    WidgetsFlutterBinding.ensureInitialized();
    var dir = await getApplicationDocumentsDirectory();
    Hive.init(dir.path);
    passwordBox = await Hive.openBox<PasswordModel>('passwordBox');
    return;
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
        body: Column(
      children: [
        WatchBoxBuilder(
          box: passwordBox,
          builder: (context, box) 
            Map<dynamic, dynamic> raw = box.toMap();
            List list = raw.values.toList();

            return ListView.builder(
              shrinkWrap: true,
              itemCount: list.length,
              itemBuilder: (context, index) 
                PasswordModel passwordModel = list[index];
                return ListTile(
                  title: Text(passwordModel.websiteName),
                  subtitle: Text(passwordModel.websiteAddress),
                );
              ,
            );
          ,
        ),
      ],
    ));
  

【问题讨论】:

【参考方案1】:

我需要一些时间来打开盒子,这就是Hive.openBox 返回Future 的原因。原因是它们的内容仍然需要加载到内存中。因此,第一次显示您的小部件时,它会打开该框,但在初始化变量之前需要一些时间。

与此同时,您必须考虑向用户显示什么:

Widget build(BuildContext context) 
  if (someBox == null) 
    return CircularProgressIndicator();
  
  // Here, you can use the box.
  ...

顺便说一句,我不建议将这些框存储在全局变量中,因为那样会很快变得混乱。使用 Hive,您只需调用一次openBox。然后,您可以使用Hive.box 同步获取对该框的引用。

因此,您也可以在调用runApp 之前在main 方法中调用Hive.openBox()。然后,该应用将需要更长的时间才能启动,但您可以随时随地获得所需的数据:

void main() 
  await Hive.openBox('my-box');
  runApp(MyApp());


// elsewhere:
Widget build(BuildContext context) 
  var box = Hive.box('my-box');
  ...

对于更复杂的状态管理,您可能也会对上次 Google I/O 中的 State Management video 感兴趣。

【讨论】:

【参考方案2】:

替换这个 ' passwordBox = await Hive.openBox&lt;PasswordModel&gt;('passwordBox');

用这个 passwordBox = await Hive.openBox&lt;PasswordModel&gt;('passwordBox'); passwordBox = Hive.box&lt;PasswordModel&gt;('passwordBox');

【讨论】:

github.com/hivedb/hive/issues/358 这个答案解决了我的错误.....

以上是关于如何解决 Box not Found 错误 Hive Flutter的主要内容,如果未能解决你的问题,请参考以下文章

Key ssd_300_vgg/block3_box/L2Normalization/gamma not found in checkpoint的解决方案

如何解决 xpc.h not found 错误?

打开网页显示404 Not Found 如何解决

如何解决 Snowflake 中仅针对任务运行出现的 Stream Not Found 错误?

private key not found 啥情况

如何解决 iPhone 中 Twitter 集成中的“LibXml/xmlreader.h Not found”错误