在 Flutter 的屏幕之间传递 Hive 框

Posted

技术标签:

【中文标题】在 Flutter 的屏幕之间传递 Hive 框【英文标题】:To pass a Hive box between screens in Flutter 【发布时间】:2021-03-05 04:28:57 【问题描述】:

我正在尝试将 Hive Box 从主屏幕传递到下一个屏幕,但无法做到。我尝试在 MaterialPageRoute 时使用 Box 类型,但它不起作用。

我正在接受来自用户的数据并尝试对其进行 CRUD 操作。我还想将一个蜂巢盒从一页传递到下一页

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart';

void main() async 
  WidgetsFlutterBinding.ensureInitialized();
  Directory dir = await getExternalStorageDirectory();
  Hive.init(dir.path);
  print(dir.path);
  await Hive.openBox<String>('box1');
  runApp(MyApp());


class MyApp extends StatelessWidget 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Hive Storage Test Run'),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  String name, pass;

  Box<String> box2;

  TextEditingController _fullname = TextEditingController();
  TextEditingController _password = TextEditingController();

  @override
  void initState() 
    super.initState();
    box2 = Hive.box<String>('box1');
  

  bool _showpass = false;

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            //Full name
            TextField(
              controller: _fullname,
              decoration: InputDecoration(labelText: 'Enter Full name'),
              onSubmitted: (String value) 
                name = value;
                Fluttertoast.showToast(msg: 'Welcome $name');
              ,
            ),
            //Password
            TextField(
              controller: _password,
              obscureText: !this._showpass,
              decoration: InputDecoration(
                labelText: 'Enter Password',
                suffixIcon: IconButton(
                  icon: Icon(
                    Icons.remove_red_eye_outlined,
                    color: this._showpass ? Colors.redAccent : Colors.blueAccent,
                  ),
                  onPressed: () 
                    setState(() => this._showpass = !this._showpass);
                  ,
                ),
              ),
              onSubmitted: (String value) 
                pass = value;
                Fluttertoast.showToast(msg: 'Password is $pass');
              ,
            ),
            SizedBox(height: 100,),
            Column(
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: <Widget>[
                    RaisedButton(
                      child: Text('Save'),
                      onPressed: () 
                        final key = _fullname.text;
                        final value = _password.text;
                        box2.put(key, value);
                        print(key);
                        print(value);
                        setState(() 
                          _fullname = TextEditingController(text: "");
                          _password = TextEditingController(text: "");
                        );
                      ,
                    ),
                    RaisedButton(
                      child: Text('Print Values'),
                      onPressed: () 
                        print(box2.getAt(0));
                      ,
                    ),
                  ],
                ),
                SizedBox(height: 30.0,),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: <Widget>[
                    RaisedButton(
                      child: Text('Load'),
                      onPressed: () 
                        if(box2.isEmpty == true)
                          Fluttertoast.showToast(msg: "No data present. Please enter new data");
                        else
                          Box box3 = box2;
                          Navigator.of(context)
                              .push(
                            MaterialPageRoute(
                              builder: (context) => Page2(box3: box3),
                            )
                          );
                        
                      ,
                    ),
                    RaisedButton(
                      child: Text("Empty Data"),
                      onPressed: () 
                        box2.clear();
                      ,
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  



class Page2 extends StatefulWidget 

  Box box3;
  Page2(box3);

  @override
  _Page2State createState() => _Page2State(box3);


class _Page2State extends State<Page2> 

  Box box3;
  _Page2State(this.box3);

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("Page 2"),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            Text("Page 2"),
            Text(box3.getAt(0)),
            RaisedButton(
              onPressed: () 
                child: Text("Back");
                Navigator.of(context).pop();
              ,
            )
          ],
        ),
      ),
    );
  

我需要将 box2 从 MyHomePage 传递到 Page2

这是我的错误....

The following NoSuchMethodError was thrown building Page2(dirty, state: _Page2State#33882):
The method 'getAt' was called on null.
Receiver: null
Tried calling: getAt(0)

The relevant error-causing widget was: 
  Page2 file:///C:/Users/harsh/androidStudioProjects/storage/lib/main.dart:142:53
When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1      _Page2State.build (package:storage/main.dart:190:23)
#2      StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
#3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
#4      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
...

【问题讨论】:

你能给我们看看错误日志吗?你说的不能是什么意思? 对不起,我不应该使用无法。更恰当的意思是我只是新手,无法自行调试错误。 【参考方案1】:

您可以直接引用您初始化的box2,而不是创建box 的新实例(在您的情况下为box3)。

 Navigator.of(context)
 .push(
     MaterialPageRoute(
        builder: (context) => Page2(box3: box2),
      )
   );

也不需要参考,你可以直接在init 状态中初始化特定的box,因为它不是async 调用它就可以正常工作

【讨论】:

我尝试了您的解决方案。错误仍然存​​在。我更改了第 2 页中的 Text 小部件。Text(box3.getAt(0)) 被替换为 Text(box3.get("Harsh")) 错误表明方法 'get' 在 null 上被调用。 感谢您的帮助。我有问题。我只需要删除为该框指定的数据类型,它就可以工作了

以上是关于在 Flutter 的屏幕之间传递 Hive 框的主要内容,如果未能解决你的问题,请参考以下文章

如何在 FLutter 中使用 pushNamed 将数据从一个屏幕传递到另一个屏幕?

flutter:块间通信,不同块之间传递数据事件

Flutter 中的 Hive 映射框

Flutter:如何在两个小部件之间传递相同的数据?

Flutter HiveDB 在 FutureBuilder 上使用框

如何解决 Box not Found 错误 Hive Flutter