【问题标题】:Flutter: Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initializedFlutter:未处理的异常:在初始化绑定之前访问了 ServicesBinding.defaultBinaryMessenger
【发布时间】:2020-01-01 12:13:37
【问题描述】:

有解决这个问题的办法吗?

堆栈跟踪:

[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.
#0      defaultBinaryMessenger.<anonymous closure> (package:flutter/src/services/binary_messenger.dart:73:7)
#1      defaultBinaryMessenger (package:flutter/src/services/binary_messenger.dart:86:4)
#2      MethodChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:140:62)
#3      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:314:35)
<asynchronous suspension>
#4      MethodChannel.invokeMapMethod (package:f<…>

【问题讨论】:

  • 将此行作为您在 main() 中的第一条语句 - WidgetsFlutterBinding.ensureInitialized();

标签: flutter dart exception


【解决方案1】:

不确定我是否有正确的答案,但在最近的一次颤振升级后我得到了同样的错误,并设法让它工作,所以我分享我的发现。

看起来该错误可能是由最近的重大更改引起的: https://groups.google.com/forum/#!msg/flutter-announce/sHAL2fBtJ1Y/mGjrKH3dEwAJ

因此,我们需要手动更改代码如下:

  • 如果您正在运行应用程序并且需要在调用 runApp() 之前访问二进制信使(例如,在 插件初始化),那么你需要显式调用 WidgetsFlutterBinding.ensureInitialized() 第一。
  • 如果您正在运行测试,您可以调用TestWidgetsFlutterBinding.ensureInitialized() 作为第一行 您的测试的 main() 方法来初始化绑定。

或者,如果你是像我这样的新手并且难以理解上述内容和#38464,你可以通过切换到测试版来暂时避免这个问题。只需运行“flutter channel beta”即可。重大更改尚未进入 beta 通道,因此在切换到 beta 通道后,您至少暂时不会收到此错误。

【讨论】:

  • 谢谢老哥,为了避免出错,我现在才用beta版!
【解决方案2】:

如果您正在等待 main() 方法,通常会发生这种情况。因此,解决方案是:

void main() {
  // add this, and it should be the first line in main method
  WidgetsFlutterBinding.ensureInitialized(); 

  // rest of your app code
  runApp(
    MaterialApp(...),
  );
}

【讨论】:

  • 不工作 - 加入中断(等待 getDatabasesPath(), 'mydb.db'),
【解决方案3】:

这个问题是在升级 Flutter 时引入的。 这背后的原因是您正在等待一些数据或在main() 中运行async 函数。

我在main() 内部初始化ScopedModel,在内部等待一些数据。

有一个非常小的修复。 只需在 void main() 中运行 WidgetsFlutterBinding.ensureInitialized(),然后再运行 runApp()。像魅力一样工作!

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(Delta(
    model: ProductDataModel(),
  ));
}

【讨论】:

  • 确保 WidgetFlutterBinding.ensureInitialized() 是 main() 的第一行。然后照常进行
  • 这有什么潜在的负面影响?所有 Flutter 应用程序都应该在 main() 方法的开头有这行吗?
  • 如果你在 main() 中使用异步方法,你需要添加这个
  • 不适用于 v1.14.4/v1.14.6 break on var databasesPath = await getDatabasesPath();
  • 如果我们不使用这一行,而使用异步方法会发生什么??我在 main() 中没有任何异步方法,但我在 MyApp 中有异步方法。
【解决方案4】:

只需在 main.dart 中添加这一行

WidgetsFlutterBinding.ensureInitialized(); 

你的代码看起来像

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  return runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider.value(
        value: AppState(),
      )
    ],
    child: MyApp(),
  ));
}

【讨论】:

    【解决方案5】:

    在我使用方向时,

    解决之前:

    void main() {
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]).then((_).{
    runApp(MyApp());
    });
    }
    

    解决使用:

    void main() {
    WidgetsFlutterBinding.ensureInitialized();
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((_) {
    runApp(MyApp());
    });
    }
    

    重点是在主类的第一行添加WidgetsFlutterBinding.ensureInitialized()

    【讨论】:

      【解决方案6】:

      在我拥有v1.12.13+hotfix.5 版本之前,我切换到v1.14.4 版本并且它工作正常。

      错误提示您应该添加WidgetsFlutterBinding.ensureInitialized();,但由于这对我不起作用,我切换到其他版本。不过要记住的一件事是,您仍然必须将 WidgetsFlutterBinding.ensureInitialized(); 添加为 main 的第一行!

      【讨论】:

        【解决方案7】:

        在 GitHub 问题 47033 上发布的答案解决了我的问题。

        问题:https://github.com/flutter/flutter/issues/47033

        对我有用的解决方案:https://github.com/flutter/flutter/issues/47033#issuecomment-571936089

        我认为这是关于颤振版本 1.12.13+hotfix 的问题,降级颤振可能也会有所帮助。

        【讨论】:

          【解决方案8】:

          解决方案:在调用异步函数之前调用WidgetsFlutterBinding.ensureInitialized();

          
          void main() async {
            WidgetsFlutterBinding.ensureInitialized();   //  ADD THIS BEFORE YOUR ASYNC FUNCTION CALL.
            await Firestore.instance.settings(...);      //  NOW YOU CAN CALL ASYNC FUNCTION.   
            ...
            runApp(
              ...
            )
          

          【讨论】:

            【解决方案9】:

            如果您尝试在隔离中执行插件本机代码,您可能会遇到这种情况。隔离处理程序文档here 很好地解释了这一点:

            插件使用一种称为平台通道的机制在 Dart 和本机方面,使用消息传递机制 MethodChannel 类型。这种机制取决于 底层 UI 引擎运行。

            这里要注意的是,隔离只会在计算量大的飞镖代码的情况下提供性能提升。插件的平台代码将再次使用主(UI)线程。

            在隔离内调用 WidgetsFlutterBinding.ensureInitialized 也会失败,因为隔离内没有底层 UI 引擎。

            【讨论】:

            • 解决方法是使用isolate_handlerflutter_isolate 生成隔离。
            • @jon :isolate_handler 文档是这么说的:If your tasks are computationally intensive on the Dart side, isolates will help a lot. If the time is spent in the plugin native side, you won't gain much unless you create your own native threads on the native side, in the plugin itself. There is nothing you can do about it in your main Dart app. 所以这里没有解决方法,除非插件本身被设计为使用多线程
            • @letiagoalves 正如我从上面的文档中看到的那样,这里没有解决方法。如果您设计插件,请确保它是多线程的。
            【解决方案10】:

            如果您从隔离中收到此错误,那么接受的解决方案将不起作用,这毫无价值。

            WidgetsFlutterBinding.ensureInitialized();
            

            只保证在主线程上的绑定。
            正在开展工作以消除限制,您可以在此处关注该问题

            https://github.com/flutter/flutter/issues/13937

            【讨论】:

              【解决方案11】:

              这可以使用WidgetsBinding.ensureInitialized() 解决,它在Dart LayerPlatform 之间建立了通信。

              如果我们需要在调用 [runApp] 之前初始化绑定,我们需要调用此方法。在绑定建立之前,Flutter 无法直接与 Flutter 引擎交互。

              void main() async {
                WidgetsFlutterBinding.ensureInitialized();   
                /// Your Code which required binding
                runApp(
                  ...
                )
              }
              

              WidgetsFlutterBinding.ensureInitialized()支持各种绑定如

              1. ServicesBinding 侦听平台消息并将它们定向到传入消息的处理程序 (BinaryMessenger)。

              2. PaintingBinding负责绑定画库。

              3. RenderBinding 将渲染树绑定到 Flutter 引擎。

              4. WidgetBinding 将小部件树绑定到 Flutter 引擎。

              5. SchedulerBinding 是运行即时任务的调度程序。

              6. SemanticsBinding绑定语义层和Flutter引擎。

              7. GestureBinding 是手势子系统的绑定。

              所有这些绑定将充当 Dart 和 Platform 之间的粘合剂。

              【讨论】:

                猜你喜欢
                • 2020-11-22
                • 2020-09-07
                • 2020-04-11
                • 2022-06-19
                • 1970-01-01
                • 1970-01-01
                • 2021-01-29
                • 1970-01-01
                • 2013-08-12
                相关资源
                最近更新 更多