Flutter Dart - 在 Isolate 中调用 sqflite 函数导致错误
Flutter Dart - Calling sqflite function in Isolate causes error
我有一个可用的 sqflite 数据库,单元测试可用。我想在 onTap 方法中调用 sqflite 方法。我知道我无法在 UI 主线程中执行 sqflite 函数(Flutter 在运行时告诉我)。所以我创建了一个 Isolate 来调用 sqflite 函数,它给出了不同的错误。如果我不调用 sqflite 函数,Isolate 会起作用,如果我只是 return 一个布尔值,Isolate 就会起作用。这是代码和异常 - 感谢您的任何建议:
来自 UI
的片段
Widget loginButton(BuildContext context) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 20.0, right: 5.0, top: 20.0, bottom: 0.0),
child: GestureDetector(
onTap: () {
if (emailController.text.length > 1 && passwordController.text.length > 7) {
/// Find user. Then...
doCheckIfFoundUser(emailController.text.trim(), passwordController.text);
} else {
printUserNotFound();
}
},
child: buttonContainer(Colors.indigo, "Login", 20.0),
),
),
);
从 UI
调用的方法
doCheckIfFoundUser(String email, String password) async {
var result;
List<String> emailPasswordList = new List();
emailPasswordList.add(email);
emailPasswordList.add(password);
var receivePort = new ReceivePort();
Isolate.spawn(callbackFunction, receivePort.sendPort);
SendPort sendPort = await receivePort.first;
var ans = await sendReceive(sendPort, emailPasswordList);
setState(() {
result = ans;
print("The value is $result - please do your thing");
});
}
隔离回调
static void callbackFunction(SendPort callerSendPort) async {
ReceivePort newIsolateReceivePort = ReceivePort();
callerSendPort.send(newIsolateReceivePort.sendPort);
var msg = await newIsolateReceivePort.first;
List<String> emailPasswordList = msg[0];
print("email: ${emailPasswordList[0]}, password: ${emailPasswordList[1]}");
bool foundUser = await searchForUser(emailPasswordList[0], emailPasswordList[1]);
SendPort replyPort = msg[1];
replyPort.send(foundUser);
}
Future sendReceive(SendPort send, message) {
ReceivePort receivePort = ReceivePort();
send.send([message, receivePort.sendPort]);
return receivePort.first;}
I/flutter ( 2073): email: email, password: Passw0rd
E/flutter ( 2073): [ERROR:flutter/runtime/dart_isolate.cc(805)] Unhandled exception:
E/flutter ( 2073): error: native function 'Window_sendPlatformMessage' (4 arguments) cannot be found
E/flutter ( 2073): #0 Window.sendPlatformMessage (dart:ui/window.dart:1089:9)
E/flutter ( 2073): #1 _DefaultBinaryMessenger._sendPlatformMessage (package:flutter/src/services/binary_messenger.dart:85:15)
E/flutter ( 2073): #2 _DefaultBinaryMessenger.send (package:flutter/src/services/binary_messenger.dart:129:12)
E/flutter ( 2073): #3 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:309:51)
E/flutter ( 2073):
E/flutter ( 2073): #4 invokeMethod (package:sqflite/src/sqflite_impl.dart:18:34)
E/flutter ( 2073):
E/flutter ( 2073): #5 SqfliteDatabaseFactoryImpl.invokeMethod (package:sqflite/src/factory_impl.dart:33:7)
E/flutter ( 2073): #6 _SqfliteDatabaseFactoryImpl&Object&SqfliteDatabaseFactoryMixin.safeInvokeMethod. (package:sqflite/src/factory_mixin.dart:22:35)
E/flutter ( 2073): #7 wrapDatabaseException (package:sqflite/src/exception_impl.dart:7:34)
E/flutter ( 2073): .
E/flutter ( 2073): #8 SqfliteDatabaseFactoryImpl.wrapDatabaseException (package:sqflite/src/factory_impl.dart:29:7).
E/flutter ( 2073): #9 _SqfliteDatabaseFactoryImpl&Object&SqfliteDatabaseFactoryMixin.safeInvokeMethod (package:sqflite/src/factory_mixin.dart:22:7).
E/flutter ( 2073): #10 _SqfliteDatabaseFactoryImpl&Object&SqfliteDatabaseFactoryMixin.getDatabasesPath (package:sqflite/src/factory_mixin.dart:136:17).
E/flutter ( 2073):
E/flutter ( 2073): #11 getDatabasesPath. (package:sqflite/sqflite.dart:166:54)
E/flutter ( 2073): #12 UsersSqflite.init (package:himrepo/controller/users_database.dart:20:47).
E/flutter ( 2073): .
E/flutter ( 2073): #13 _LoginPageState.searchForUser. (package:himrepo/ui/login.dart:268:24).
E/flutter ( 2073): .
E/flutter ( 2073): #14 _LoginPageState.callbackFunction(package:himrepo/ui/login.dart:166:28).
E/flutter ( 2073): .
E/flutter ( 2073): #15 _startIsolate.. (dart:isolate-patch/isolate_patch.dart:304:17).
E/flutter ( 2073): #16 _RawReceivePortImpl._handleMessage(dart:isolate-patch/isolate_patch.dart:172:12).
直接执行Sqflite方法给出
E/AndroidRuntime( 6628): FATAL EXCEPTION: Sqflite
E/AndroidRuntime( 6628): java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: Sqflite
E/AndroidRuntime( 6628): at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:794)
E/AndroidRuntime( 6628): at io.flutter.embedding.engine.FlutterJNI.invokePlatformMessageResponseCallback(FlutterJNI.java:727)
E/AndroidRuntime( 6628): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:140)
E/AndroidRuntime( 6628): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.success(MethodChannel.java:225)
E/AndroidRuntime( 6628): at com.tekartik.sqflite.SqflitePlugin.run(SqflitePlugin.java:778)
E/AndroidRuntime( 6628): at android.os.Handler.handleCallback(Handler.java:873)
E/AndroidRuntime( 6628): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 6628): at android.os.Looper.loop(Looper.java:193)
E/AndroidRuntime( 6628): at android.os.HandlerThread.run(HandlerThread.java:65)
感谢@pskink 的帮助。 Isolate 有效,但是当 运行 sqflite 来自 Widget onTap 事件时,我遇到了异常。事实证明,我在 pubspec.yaml 中包含的一个插件 (json_annotation) 以某种方式导致了异常:"Methods marked with @UiThread must be executed on the main thread. Current thread: Sqflite"。删除该插件后,该应用程序可以正常工作。
我有一个可用的 sqflite 数据库,单元测试可用。我想在 onTap 方法中调用 sqflite 方法。我知道我无法在 UI 主线程中执行 sqflite 函数(Flutter 在运行时告诉我)。所以我创建了一个 Isolate 来调用 sqflite 函数,它给出了不同的错误。如果我不调用 sqflite 函数,Isolate 会起作用,如果我只是 return 一个布尔值,Isolate 就会起作用。这是代码和异常 - 感谢您的任何建议:
来自 UI
的片段 Widget loginButton(BuildContext context) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 20.0, right: 5.0, top: 20.0, bottom: 0.0),
child: GestureDetector(
onTap: () {
if (emailController.text.length > 1 && passwordController.text.length > 7) {
/// Find user. Then...
doCheckIfFoundUser(emailController.text.trim(), passwordController.text);
} else {
printUserNotFound();
}
},
child: buttonContainer(Colors.indigo, "Login", 20.0),
),
),
);
从 UI
调用的方法doCheckIfFoundUser(String email, String password) async {
var result;
List<String> emailPasswordList = new List();
emailPasswordList.add(email);
emailPasswordList.add(password);
var receivePort = new ReceivePort();
Isolate.spawn(callbackFunction, receivePort.sendPort);
SendPort sendPort = await receivePort.first;
var ans = await sendReceive(sendPort, emailPasswordList);
setState(() {
result = ans;
print("The value is $result - please do your thing");
});
}
隔离回调
static void callbackFunction(SendPort callerSendPort) async {
ReceivePort newIsolateReceivePort = ReceivePort();
callerSendPort.send(newIsolateReceivePort.sendPort);
var msg = await newIsolateReceivePort.first;
List<String> emailPasswordList = msg[0];
print("email: ${emailPasswordList[0]}, password: ${emailPasswordList[1]}");
bool foundUser = await searchForUser(emailPasswordList[0], emailPasswordList[1]);
SendPort replyPort = msg[1];
replyPort.send(foundUser);
}
Future sendReceive(SendPort send, message) {
ReceivePort receivePort = ReceivePort();
send.send([message, receivePort.sendPort]);
return receivePort.first;}
I/flutter ( 2073): email: email, password: Passw0rd
E/flutter ( 2073): [ERROR:flutter/runtime/dart_isolate.cc(805)] Unhandled exception:
E/flutter ( 2073): error: native function 'Window_sendPlatformMessage' (4 arguments) cannot be found
E/flutter ( 2073): #0 Window.sendPlatformMessage (dart:ui/window.dart:1089:9)
E/flutter ( 2073): #1 _DefaultBinaryMessenger._sendPlatformMessage (package:flutter/src/services/binary_messenger.dart:85:15)
E/flutter ( 2073): #2 _DefaultBinaryMessenger.send (package:flutter/src/services/binary_messenger.dart:129:12)
E/flutter ( 2073): #3 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:309:51)
E/flutter ( 2073):
E/flutter ( 2073): #4 invokeMethod (package:sqflite/src/sqflite_impl.dart:18:34)
E/flutter ( 2073):
E/flutter ( 2073): #5 SqfliteDatabaseFactoryImpl.invokeMethod (package:sqflite/src/factory_impl.dart:33:7)
E/flutter ( 2073): #6 _SqfliteDatabaseFactoryImpl&Object&SqfliteDatabaseFactoryMixin.safeInvokeMethod. (package:sqflite/src/factory_mixin.dart:22:35)
E/flutter ( 2073): #7 wrapDatabaseException (package:sqflite/src/exception_impl.dart:7:34) E/flutter ( 2073): .
E/flutter ( 2073): #8 SqfliteDatabaseFactoryImpl.wrapDatabaseException (package:sqflite/src/factory_impl.dart:29:7).
E/flutter ( 2073): #9 _SqfliteDatabaseFactoryImpl&Object&SqfliteDatabaseFactoryMixin.safeInvokeMethod (package:sqflite/src/factory_mixin.dart:22:7). E/flutter ( 2073): #10 _SqfliteDatabaseFactoryImpl&Object&SqfliteDatabaseFactoryMixin.getDatabasesPath (package:sqflite/src/factory_mixin.dart:136:17). E/flutter ( 2073): E/flutter ( 2073): #11 getDatabasesPath. (package:sqflite/sqflite.dart:166:54) E/flutter ( 2073): #12 UsersSqflite.init (package:himrepo/controller/users_database.dart:20:47). E/flutter ( 2073): . E/flutter ( 2073): #13 _LoginPageState.searchForUser. (package:himrepo/ui/login.dart:268:24). E/flutter ( 2073): . E/flutter ( 2073): #14 _LoginPageState.callbackFunction(package:himrepo/ui/login.dart:166:28). E/flutter ( 2073): . E/flutter ( 2073): #15 _startIsolate.. (dart:isolate-patch/isolate_patch.dart:304:17). E/flutter ( 2073): #16 _RawReceivePortImpl._handleMessage(dart:isolate-patch/isolate_patch.dart:172:12).
直接执行Sqflite方法给出
E/AndroidRuntime( 6628): FATAL EXCEPTION: Sqflite
E/AndroidRuntime( 6628): java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: Sqflite
E/AndroidRuntime( 6628): at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:794)
E/AndroidRuntime( 6628): at io.flutter.embedding.engine.FlutterJNI.invokePlatformMessageResponseCallback(FlutterJNI.java:727)
E/AndroidRuntime( 6628): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:140)
E/AndroidRuntime( 6628): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.success(MethodChannel.java:225)
E/AndroidRuntime( 6628): at com.tekartik.sqflite.SqflitePlugin.run(SqflitePlugin.java:778)
E/AndroidRuntime( 6628): at android.os.Handler.handleCallback(Handler.java:873)
E/AndroidRuntime( 6628): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 6628): at android.os.Looper.loop(Looper.java:193)
E/AndroidRuntime( 6628): at android.os.HandlerThread.run(HandlerThread.java:65)
感谢@pskink 的帮助。 Isolate 有效,但是当 运行 sqflite 来自 Widget onTap 事件时,我遇到了异常。事实证明,我在 pubspec.yaml 中包含的一个插件 (json_annotation) 以某种方式导致了异常:"Methods marked with @UiThread must be executed on the main thread. Current thread: Sqflite"。删除该插件后,该应用程序可以正常工作。