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() 前的插件调用可能报错情况 |