Skip to content

[已解決] ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.

在使用 Flutter 開發 APP 時,若是碰到像是 firebase 或 sqflite 等套件需要初始化時,但偏偏它們又是非同步(asynchronously)操作時,往往會讓我們得到以下報錯訊息:

ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.


我們可以看到以下這張 Flutter 的架構圖,其中分成 Framework、Engine、Embedder 等數個不同的區塊,每個區塊中又有各種模組與功能。

而像是 firebase 與 sqflite 等套件正是需要這些模組與功能來完成初始化。但正如上方所述,這些操作是非同步的。所以,我們必須確保,一個叫做 WidgetsBinding 的物件已經被初始化、建立起來。

這樣一來,這些非同步初始化的套件才能正常工作。


解決方法

說穿了,其實解決問題並不複雜。我們可以想像成以下簡化的流程:

  • 我們有個 A 工具,需要 B 工具才能運作
  • A 工具會比 B 工具更早載入 => 程式報錯!
  • 我們先寫段程式確保 B 工具載入,再載入 A 工具 => 程式成功運行!

也就說,我們可以在以下的程式碼中,加入:

WidgetsFlutterBinding.ensureInitialized();


以此來確保 WidgetsBinding 已經初始化。

整體程式碼看起來會長得像以下這段程式碼:

import 'dart:async';

import 'package:flutter/widgets.dart';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';


void main() async {
  // Avoid errors
  WidgetsFlutterBinding.ensureInitialized();

  // Open the database
  final Future<Database> database = openDatabase(

    // Ensure the path is correctly for any platform
    join(await getDatabasesPath(), "Human_database.db"),
    onCreate: (db, version) {
      return db.execute(
          "CREATE TABLE Human("
              "id INTEGER PRIMARY KEY,"
              "name TEXT,"
              "age INTEGER,"
              "FAT BOOLEAN)"
      );
    },

    // Set the database version
    version: 1,
  );

  print("OK!");
}


Output:

OK!


可以發現,拔掉以下這段程式碼

WidgetsFlutterBinding.ensureInitialized();


程式是會報錯的。


References


Read More

Tags:

Leave a Reply