flutter:确保初始化WidgetsFlutterBinding.ensureInitialized

  1. ensureInitialized的作用
  2. 常见使用场景
  3. 什么时候必须要用
  4. 代码执行顺序
  5. Binding 是什么时候创建的?

ensureInitialized的作用

在 Flutter 里 WidgetsFlutterBinding.ensureInitialized(); 主要作用是**确保 Flutter 的引擎和框架层已经完成绑定和初始化**,通常在 main() 函数中调用。

Flutter 程序启动时,会创建一个 Binding(绑定类),用来把 Flutter 引擎 (engine)Flutter 框架 (framework) 连接起来。

  • WidgetsBinding:负责调度、手势、渲染、widget 生命周期等。

  • WidgetsFlutterBinding:在 WidgetsBinding 的基础上,把所有和 Flutter App 运行相关的 Binding 组合起来(渲染、手势、scheduler、服务等)。

  • 如果你直接调用依赖于 Flutter 引擎的 API,而 Binding 还没初始化,就会报错。

ensureInitialized() 的作用

  • 如果 WidgetsFlutterBinding 已经初始化,就直接返回实例;
  • 如果还没初始化,就会创建一个新的 WidgetsFlutterBinding 实例。

等价于:

if (WidgetsBinding.instance == null) {
  WidgetsFlutterBinding();
}

常见使用场景

一般写在 main() 方法开头,尤其是当你在 runApp() 前需要执行一些依赖 Flutter 引擎的操作时:

void main() async {
  // 确保 Flutter 引擎和框架初始化
  WidgetsFlutterBinding.ensureInitialized();

  // 比如使用插件:SharedPreferences、PathProvider、Firebase.initializeApp()
  prefs = await SharedPreferences.getInstance();

  runApp(MyApp());
}

什么时候必须要用

需要在 runApp() 之前调用 异步插件(这些插件底层需要引擎支持)。例如:

  • 读取本地存储路径 (path_provider)
  • 初始化 Firebase (firebase_core)
  • 使用 SharedPreferences
  • 操作数据库 (如 sqflite)

如果不调用,可能会报类似:

ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.

代码执行顺序

void main() async {
  // 确保 Flutter 引擎和框架初始化
  WidgetsFlutterBinding.ensureInitialized();

  // 比如使用插件:SharedPreferences、PathProvider、Firebase.initializeApp()
  prefs = await SharedPreferences.getInstance();

  runApp(MyApp());
}

Flutter 引擎启动(C++ 层)

  • 初始化 Dart 运行时
  • 加载 Dart VM
  • 加载你的 main.dart

Dart 层开始执行

  • 进入你的 main() 方法
  • 此时Dart 层还没有任何 Binding 实例
  • Flutter 框架(WidgetsBinding/RenderBinding 等)不会自动执行任何方法,因为这些都是通过 Dart 类实例化才会创建的

调用 WidgetsFlutterBinding.ensureInitialized()

  • 检查 WidgetsBinding.instance
  • 如果 null → 创建一个 WidgetsFlutterBinding 实例
  • 如果已存在 → 直接返回实例

后续插件初始化和 runApp() 执行

从 Dart 层 main() 开始到 ensureInitialized() 执行之前不会有 Flutter 框架自动创建 Binding。所以,你这段时间里 WidgetsBinding.instance 一定是 null。也就是说,ensureInitialized() 第一次被调用时,一定是主动创建 Binding

gantt
    title Flutter 程序启动流程时间线
    dateFormat  HH:mm:ss
    axisFormat  %H:%M:%S

    section Flutter 引擎
    启动引擎、初始化 Dart VM      :a1, 00:00:00, 1s

    section Dart 层
    执行 main()                     :a2, after a1, 1s
    手动调用 WidgetsFlutterBinding.ensureInitialized() :a3, after a2, 1s
    ─> 如果调用,Binding 立即创建   :a4, after a3, 0.5s
    插件初始化(如 SharedPreferences):a5, after a4, 1s
    runApp(MyApp())                  :a6, after a5, 1s
    ─> 如果没有手动调用 ensureInitialized :a7, after a6, 0.5s Binding 在 runApp 内被创建

Binding 是什么时候创建的?

runApp() 内部会调用 WidgetsFlutterBinding.ensureInitialized()

runApp() 源码里:

WidgetsFlutterBinding.ensureInitialized();

所以如果你没有手动调用 ensureInitialized(),Binding 会runApp() 内部被创建

注意:这就意味着任何在 runApp() 之前调用依赖 Binding 的操作(比如插件初始化、平台通道调用)都会失败。

情况 Binding 创建时机 安全调用插件
手动调用
WidgetsFlutterBinding
.ensureInitialized()
main() 里调用时,立即创建 runApp() 前就可以安全调用
不手动调用 runApp() 内部才创建 runApp() 前的插件调用可能报错情况

×

喜欢就点赞,疼爱就打赏