Flutter中的热更新
首先来了解一下 JIT & AOT
JIT & AOT
JIT全称是Just In Time
,代码可以在程序执行时期编译,因为要在程序执行前进行分析、编译,JIT编译可能会导致程序执行时间较慢;而AOT编译,全称Ahead Of Time
,是在程序运行前就已经编译,从开发者修改代码到编译的过程较慢,但运行时不需要进行分析、编译,因此执行速度更快。
Flutter使用了独特的编译模式,开发阶段下,使用Kernel Snapshot
模式(对应JIT编译),将dart代码生成标记化的源代码,运行时编译,解释执行;release阶段,ios使用AOT编译
,编译器将dart代码生成汇编代码,最终生成app.framwork,android使用了Core JIT编译
,dart转化为二进制模式,在VM启动前载入。
hot reload 原理
Flutter通过将新的代码注入到正在运行的DartVM中,来实现Hot Reload这种神奇的效果,在DartVM将程序中的类结构更新完成后,Flutter会立即重建整个控件树,从而更新界面。

触发热刷新时Flutter会检测发生改变的Dart文件,将其同步到App私有缓存目录下,DartVM加载并且修改对应的类或者方法,重建控件树后立即可以在设备上看到效果。
热刷新限制
并不是所有的代码改动都可以通过热刷新来更新:
-
编译错误,如果修改后的Dart代码无法通过编译,Flutter会在控制台报错,这时需要修改对应的代码。
-
控件类型从StatelessWidget到StatefulWidget的转换,因为Flutter在执行热刷新时会保留程序原来的state,而某个控件从stageless→stateful后会导致Flutter重新创建控件时报错“myWidget is not a subtype of StatelessWidget”,而从stateful→stateless会报错“type 'myWidget' is not a subtype of type 'StatefulWidget' of 'newWidget'”。
-
全局变量和静态成员变量,这些变量不会在热刷新时更新。
-
修改了main函数中创建的根控件节点,Flutter在热刷新后只会根据原来的根节点重新创建控件树,不会修改根节点。
-
某个类从普通类型转换成枚举类型,或者类型的泛型参数列表变化,都会使热刷新失败。
-
热刷新无法实现更新时,执行一次热重启(Hot Restart)就可以全量更新所有代码,同样不需要重启App,区别是restart会将所有Dart代码打包同步到设备上,并且所有状态都会重置