【问题标题】:how to save data in Hive database when receiving data in the background?后台接收数据时如何将数据保存在Hive数据库中?
【发布时间】:2021-10-11 04:22:56
【问题描述】:

当应用在后台接收 Firebase 云消息传递 (FCM) 推送通知数据时,我在将数据保存到 Hive 时遇到问题。

我有一个静态方法来设置这样的配置单元

static Future<void> setUpHive() async {
    try {

      await Hive.initFlutter();

      if (!Hive.isBoxOpen("Box Name")) {
          await Hive.openBox("Box Name");
      }

    } catch (error) {
      print(error.toString());
    }
}

我在 main 这样的函数中使用 setUpHive 静态方法

Future<void> main() async {

  await HiveHelper.setUpHive();

  runApp(
    MyApp(),
  );
}

当应用程序在后台,然后它收到 FCM 消息,然后下面的代码将被调用。之后我尝试更改存储在 Hive 框中的数据

Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
    // when receive FCM message when app is in the background, this block will be executed
    
    // set up the hive first
    await HiveHelper.setUpHive(); 

    // then I try to change the data stored in the Hive box
    final myBox = Hive.box("BOX NAME");
    myBox.put("key", 12345);
}

收到 FCM 后台数据后似乎没问题,但是当我完全关闭应用程序并再次调用 main 时,尝试像这样打开盒子时出现错误

   static Future<void> setUpHive() async {
        try {

          await Hive.initFlutter();

          if (!Hive.isBoxOpen("Box Name")) {
              await Hive.openBox("Box Name"); // Error in this line
          }

        } catch (error) {
          print(error.toString());
        }
    }

错误是:

HiveError:这不应该发生。请在 GitHub 上打开一个问题。 E/颤振(13142):[错误:颤振/lib/ui/ui_dart_state.cc(199)] 未处理的异常:HiveError:这不应该发生。请打开一个 GitHub上的问题。 E/flutter (13142): #0 BinaryReaderImpl.readFrame (包:hive/src/binary/binary_reader_impl.dart:250:7) E/颤振

我试图找到解决方案,我从here about Using Hive DB in a Background Process 找到了类似的问题,据说

莱西姆:

很遗憾,Hive 不支持多次打开盒子 隔离。这意味着您可以关闭主隔离中的框, 在您的后台隔离中更新它并在主隔离中重新打开它 或者您将数据从后台传递到主要隔离区,然后 在那里执行更新...

我是 Flutter 新手,不懂他说什么。请帮忙:(

【问题讨论】:

    标签: flutter flutter-hive


    【解决方案1】:

    应用进入后台后,您需要关闭主隔离中的蜂巢盒。当它发生时,您需要在后台隔离中进行 CRUD。如果您想在两个隔离之间同步数据(因为它们不共享相同的配置单元数据),那么您需要隔离之间的双向通信。

    这是两个隔离体之间通信的示例代码。

    import 'dart:io'; // for exit();
    import 'dart:async';
    import 'dart:isolate';
    
    Future<SendPort> initIsolate() async {
      Completer completer = new Completer<SendPort>();
      ReceivePort isolateToMainStream = ReceivePort();
    
      isolateToMainStream.listen((data) {
        if (data is SendPort) {
          SendPort mainToIsolateStream = data;
          completer.complete(mainToIsolateStream);
        } else {
          print('[isolateToMainStream] $data');
        }
      });
    
      Isolate myIsolateInstance = await Isolate.spawn(myIsolate, isolateToMainStream.sendPort);
      return completer.future;
    }
    
    void myIsolate(SendPort isolateToMainStream) {
      ReceivePort mainToIsolateStream = ReceivePort();
      isolateToMainStream.send(mainToIsolateStream.sendPort);
    
      mainToIsolateStream.listen((data) {
        print('[mainToIsolateStream] $data');
        exit(0);
      });
    
      isolateToMainStream.send('This is from myIsolate()');
    }
    
    void main() async {
      SendPort mainToIsolateStream = await initIsolate();
      mainToIsolateStream.send('This is from main()');
    }
    

    更多信息请到https://medium.com/@lelandzach/dart-isolate-2-way-communication-89e75d973f34

    【讨论】:

      【解决方案2】:

      你可以试试下面的代码。基本思想是将数据从后台隔离发送到主隔离。

      Future<void> backgroundMessageHandler(RemoteMessage msg){
        IsolateNameServer.lookupPortByName('main_port')?.send(msg);
      }
      
      @override
      void initState(){
        super.initState();
      
        ReceivePort receivePort = ReceivePort();
        IsolateNameServer.registerPortWithName(receivePort.sendPort,'main_port');
      
        receivePort.listen((message) {
          if(message is RemoteMessage){
            //TODO: save your data in hive box
          }
        }
          
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-08
        • 1970-01-01
        • 2012-08-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多