likes
comments
collection
share

Flutter runApp -- WidgetsFlutterBinding

作者站长头像
站长
· 阅读数 3

前面我们分析学习了Flutter的项目结构,今天我们来看看main.dart里面的这样一段代码

void main() {
   runApp(const MyApp());
}

Flutter 程序入口

main方法一般是Flutter App的入口,它内部通过调用runApp方法应用整个Widget添加和运行。而且我们可以在不同的时机再次调用runApp,比如在app 启动的时候因为数据加载等问题会有一个空白屏幕的时间。这个时候我们就可以通过多次调用runApp来实现,简单的例子如下:

void main() {

  runApp(const SplashScreen()); //

  Future.delayed(Duration(seconds: 10), () {
       runApp(const MyApp());
   });
}

runApp

在外部通过调用runApp方法实现整个Widget效果,那么我们就去看看runApp方法的实现,如下:

void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()
  ..scheduleAttachRootWidget(app)
  ..scheduleWarmUpFrame();
}

这里可以看到上面有三行代码,分别代表了Flutter App启动的三个步骤:

  • WidgetsFlutterBinding 初始化(ensureInitialized()),与 Flutter Engine 进行通信。
  • 绑定根节点创建flutter 著名的三棵树(scheduleAttachRootWidget(app))进行布局。
  • 将布局出来的树进行渲染(scheduleWarmUpFrame()

今天我们讲WidgetsFlutterBinding,不过也说WidgetsFlutterBinding,因为后面俩个自己学习的还是半桶水😭。

什么是WidgetsFlutterBinding?

官方的文档Widgets Binding,以及源代码里面注解有一句话是这样的:

The glue between the widgets layer and the Flutter engine.

你可以看到SystemChannels用于建立通信(MethodChannel)与引擎(其他语言环境的系统)。

mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {

@override

void initInstances() {

super.initInstances();

_instance = this;

。。。。。。

SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
。。。。。。
return true;
}());

}

我们看头部一行代码可以通过字面意思可以发现WidgetsFlutterBinding 继承自 BindingBase,也带有很多 XXXBinding。WidgetsFlutterBinding 将是 Widget 架构和 Flutter Engine 连接的核心桥梁,也是整个 Flutter 应用层的核心。通过 ensureInitialized() 方法我们可以得到一个全局单例 WidgetsFlutterBinding。

稍微解释一下各种Binding的作用。

  • ServicesBinding:Flutter System 平台消息监听绑定类。即Platform与Flutter Layer通信相关服务,同时注册并监听应用生命周期回调。
  • SchedulerBinding:Flutter 绘制调度器相关绑定类,调试统计绘制过程持续时间等编译模式下的操作。
  • GestureBinding:Flutter Gesture事件绑定,处理屏幕事件分发和事件回调,其初始化方法的关键点是回调事件处理_handlePointerDataPacket函数被赋值给window的属性,以便window在接收到屏幕事件后调用,window的实例是 Framework Layer 和 Engine 桥接层用来处理屏幕事件。
  • RendererBinding:引擎之间的渲染树和Flutter Binding类,内部重点是持有渲染树的根节点。
  • SemanticsBinding:引擎之间的语义树和 Flutter Binding 类。

Flutter runApp -- WidgetsFlutterBinding

有时候我们会在发现有的app 在在运行应用程序之前先与 Flutter Engine 进行通信,所以要先将WidgetsFlutterBinding.ensureInitialized()提前。

void main() {
   WidgetsFlutterBinding.ensureInitialized();
   runApp(const MyApp()); //
}

SystemChannels

在binding 初始化里面有这个一句话:

SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);

如果点击进去查看SystemChannels源码,可以看到内容使用了MethodChannel(l方法通道)、EventChanne(事件通道)、以及生命周期的东西。简单的用表格总结如下(可能不全。):

种类作用Flutter Service
lifecycle生命周期widget
navigation导航widget
systembinding中使用widget
accessibility辅助功能(如读取文本信息)PlatformViews, Semantics
platform系统设置(画面旋转等)SemanticsService,RouteNotificationMessages etc.
platform_views特定平台视图操作AndroidView, UiKitView
skia图形引擎-
keyEvent键输入RawKeyEvent
textInput文本输入TextInput, AndroidView, UiKitView

WidgetsBindingObserver

而关于 WidgetsBinding在Widget里面的具体使用,可以查看WidgetsBindingObserver源码,下面举一个简单的使用例子:

class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver { 

    AppLifecycleState _state; 
    
    @override void initState() { 
        super.initState();       WidgetsBinding.instance.addObserver(this); 
     } 
     
     @override void dispose() {   WidgetsBinding.instance.removeObserver(this); 
     super.dispose(); 
  } 
  
  @override void didChangeAppLifecycleState(AppLifecycleState state){ print('state = $state'); 
  }
}