美文网首页Flutter
Flutter - Hot Reload

Flutter - Hot Reload

作者: LouisXWB | 来源:发表于2020-01-18 23:09 被阅读0次

    flutter 通过 Hot Reload 可以实现代码的动态刷新,可以帮助开发者方便快速的调试代码,构建 UI,主要是调试UI。

    使用

    Android Studio上直接cmd+s保存代码就会启动Hot Reload,需要注意的是只有 Debug 模式才能使用 Hot Reload。

    工作原理

    Hot Reload 只能在 Debug 模式下使用,是因为 Debug 模式下,Flutter 采用的是 JIT 动态编译,代码是运行在 Dart VM 上,JIT 将 Dart 编译成可以运行在 Dart VM 上的 Dart Kernel,Dart Kernel 可以动态更新,所以就实现了代码的实时更新功能。

    当调用 Hot Reload 时:

    • 首先会扫描代码,找到上次编译之后有变化的 Dart 代码。
    • 在将这些变化的 Dart 代码转化为增量的 Dart Kernel 文件。
    • 将增量的 Dart Kernel 文件发送到正在移动设备上运行的 Dart VM。
    • Dart VM 会将发来的增量 Dart Kernel 文件和原有的 Dart Kernel 文件合并,然后重新加载全新的 Dart Kernel。
    • 重新加载了 Dart Kernel,却不会重新执行代码,而是通知 Flutter Framework 重建 Widget。

    所以 Flutter 的 Hot Reload 并不会重新执行一遍代码,而是触发 Flutter 重新绘制,并且会保留 Flutter 之前的状态,所以 Hot Reload 也被称为有状态的热重载。

    不能使用 Hot Reload 的场景

    在理解了 Hot Reload 的原理之后,可以看到 Hot Reload 的使用场景是有一些限制的,接下来我们在看一下不能使用 Hot Reload的 场景:

    1. 代码更改会影响 APP 状态的不能使用 Hot Reload

    如果你的代码更改会影响 APP 的状态,使得代码更改之后的状态和代码更改之前的状态不一样,那么 Hot Reload 就不会生效,例如:

    class MyWidget extends StatelessWidget {
      Widget build(BuildContext context) {
        return GestureDetector(onTap: () => print('T'));
      }
    }
    

    这段代码,运行 App 之后,将 StatelessWidget 改为 StatefulWidget:

    class MyWidget extends StatefulWidget {
      @override
      State<MyWidget> createState() => MyWidgetState();
    }
    
    class MyWidgetState extends State<MyWidget> { /*...*/ }
    

    因为 Hot Reload 会保留状态,在代码更改之前,MyWidget 是 StatelessWidget ,将 StatelessWidget 改为 StatefulWidget ,如果 Hot Reload 成功,那么 MyWidget 会变成 StatefulWidget ,与它之前的状态就会不兼容的,所以 Hot Reload 是不会成功的。

    2. 全局变量( global variables)和静态字段(static fields)的更改不能使用 Hot Reload

    在 Flutter 中,全局变量和静态字段被视为状态,因此在 Hot Reload 期间不会重新初始化。

    如下的代码:

    final sampleTable = [
    Table("T1"),
    Table("T2"),
    Table("T3"),
    Table("T4"),
    ];
    运行 App 之后,如果做了如下的更改:

    final sampleTable = [
    Table("T1"),
    Table("T2"),
    Table("T3"),
    Table("T10"), // 修改这里的值
    ];
    运行 Hot Reload,是不会成功的,所以全局变量和静态字段不能使用 Hot Reload。

    3. main() 方法里的更改不能使用 Hot Reload

    因为 main() 方法不会因重建窗口小部件树而重新执行,所以更改 main() 方法里的代码,不会在 Hot Reload 之后看到效果。

    例如,如下的代码:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      Widget build(BuildContext context) {
        return GestureDetector(onTap: () => print('tapped'));
      }
    }
    

    在运行App后,更改如下:

    import 'package:flutter/widgets.dart';
    
    void main() {
      runApp(const Center(
          child: const Text('Hello', textDirection: TextDirection.ltr)));
    }
    

    Hot Reload 之后,不会看到任何变化。

    1. 枚举类型更改为常规的类或者常规的类变为枚举类型也不能使用 HotReload
      例如,如下的例子:
    enum Color {
      red,
      green,
      blue
    }
    

    改为:

    class Color {
      Color(this.i, this.j);
      final int i;
      final int j;
      }
    
    1. 修改通用类型声明也不能使用 HotReload
      例如,如下的例子:
    class A<T> {
      T i;
    }
    

    改为:

    class A<T, V> {
      T i;
      V v;
    }
    

    Hot Reload VS Hot Restart

    针对上面不能使用 Hot Reload 的情况,就需要使用 Hot Restart。Hot Restart 可以完全重启您的应用程序,但却不用结束调试会话。这个特性可以用来快速调试代码,对于业务代码可能会出现 Hot Restart 失败的情况,这时直接 Hot Reload 也就是直接run就行了,Hot Restart 大部分使用场景还是用来调整UI或者业务代码上小而不改变状态的改动。

    相关文章

      网友评论

        本文标题:Flutter - Hot Reload

        本文链接:https://www.haomeiwen.com/subject/jqplzctx.html