Flutter Dart - вызов функции sqflite в Isolate вызывает ошибку - PullRequest
0 голосов
/ 29 июня 2019

У меня есть база данных sqflite, которая работает, модульные тесты работают.Я хочу вызвать метод sqflite в методе onTap.Я понимаю, что не могу выполнить функцию sqflite в основном потоке пользовательского интерфейса (Flutter сообщает мне об этом во время выполнения).Поэтому я создал Isolate для вызова функции sqflite, которая выдает другую ошибку.Isolate работает, если я не вызываю функцию sqflite, работает, если я просто возвращаю bool.Вот код и исключение - спасибо за любые предложения:


Фрагмент из пользовательского интерфейса

    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),
        ),
      ),
    );

Метод, вызванный из пользовательского интерфейса

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 / флаттер (2073): электронная почта: электронная почта, пароль: Passw0rd

E / флаттер (2073): [ОШИБКА: флаттер / среда выполнения /dart_isolate.cc (805)] Необработанное исключение:

E / flutter (2073): ошибка: не найдена собственная функция 'Window_sendPlatformMessage' (4 аргумента)

E / flutter (2073):# 0 Window.sendPlatformMessage (dart: ui / window.dart: 1089: 9)

E / flutter (2073): # 1 _DefaultBinaryMessenger._sendPlatformMessage (пакет: flutter / src / services / binary_messenger.dart: 85: 15)

E / flutter (2073): # 2 _DefaultBinaryMessenger.send (пакет: flutter / src / services / binary_messenger.dart: 129: 12)

E / flutter (2073): # 3 MethodChannel.invokeMethod (пакет: flutter / src / services / platform_channel.dart: 309: 51)

E / флаттер (2073):

E / флаттер(2073): # 4 invokeMethod (пакет: sqflite / src / sqflite_impl.dart: 18: 34)

E / флаттер (2073):

E / флаттер (2073): # 5SqfliteDatabaseFactoryImpl.invokeMethod (пакет: sqflite / src / factory_impl.dart: 33: 7)

E / flutter (2073): # 6 _SqfliteDatabaseFactoryImpl & Object & SqfliteDatabaseFactoryDvoMixsa.Mixin.(пакет: sqflite / src / factory_mixin.dart: 22: 35)

E / flutter (2073): # 7 wrapDatabaseException (пакет: sqflite / src / exception_impl.dart: 7: 34) E / flutter (2073):

E / flutter (2073): # 8 SqfliteDatabaseFactoryImpl.wrapDatabaseException (пакет: sqflite / src / factory_impl.dart: 29: 7).

E / flutter (2073): # 9 _SqfliteDatabaseFactoryImpl & Object & SqfliteDatabaseFactoryMixin.safeInvokeMethod (пакет: sqflite / src / factory_mixin.dart: 22: 7).E / flutter (2073): # 10 _SqfliteDatabaseFactoryImpl & Object & SqfliteDatabaseFactoryMixin.getDatabasesPath (пакет: sqflite / src / factory_mixin.dart: 136: 17).E / flutter (2073): E / flutter (2073): # 11 getDatabasesPath.(пакет: sqflite / sqflite.dart: 166: 54) E / flutter (2073): # 12 UsersSqflite.init (пакет: himrepo / controller / users_database.dart: 20: 47).E / флаттер (2073):E / flutter (2073): # 13 _LoginPageState.searchForUser.(Упаковка: himrepo / щ / login.dart: 268: 24).E / флаттер (2073):E / flutter (2073): # 14 _LoginPageState.callbackFunction (пакет: himrepo / ui / login.dart: 166: 28).E / флаттер (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$1.success(MethodChannel.java:225)
E/AndroidRuntime( 6628):    at com.tekartik.sqflite.SqflitePlugin$6.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)


1 Ответ

0 голосов
/ 30 июня 2019

Спасибо @pskink за помощь.Изолятор работает, но я получал исключения при запуске sqflite из события Widget onTap.Оказалось, что плагин (json_annotation), который я включил в свой pubspec.yaml, каким-то образом способствовал исключению: «Методы, помеченные @UiThread, должны выполняться в главном потоке. Текущий поток: Sqflite».После удаления этого плагина приложение работает.

...