应用程序在后台时接收 Firebase Cloud Messaging (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());
}
}
我在像这样的
setUpHive
函数中使用main
静态方法
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/flutter(13142):[错误:flutter/lib/ui/ui_dart_state.cc(199)] 未处理的异常:HiveError:这不应该发生。请打开一个 GitHub 上的问题。 E/flutter (13142): #0 BinaryReaderImpl.readFrame (包:hive/src/binary/binary_reader_impl.dart:250:7) 电子/颤振
我尝试找到解决方案,并且我从这里找到了类似的问题关于在后台进程中使用Hive DB并且据说
雷西姆:
不幸的是,Hive 不支持多个开箱 隔离。这意味着您可以关闭主隔离区中的盒子, 在后台隔离中更新它并在主隔离中重新打开它 或者将数据从后台传递到主隔离区并 在那里执行更新...
我是Flutter新手,不太明白他说的是什么。请帮忙:(
您可以尝试以下代码。基本思想是将数据从后台隔离发送到主隔离。
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
}
}
}
应用程序进入后台后,您需要关闭主隔离区中的蜂巢盒。当它发生时,您需要在后台隔离中进行 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
专门针对这种情况创建了包isolated_box。 Box 已经隔离并可重复使用,您仍然可以流式传输更改。