Flutter - Hot Reload

flutter 通過 Hot Reload 可以實現(xiàn)代碼的動態(tài)刷新,可以幫助開發(fā)者方便快速的調試代碼,構建 UI,主要是調試UI。

使用

Android Studio上直接cmd+s保存代碼就會啟動Hot Reload,需要注意的是只有 Debug 模式才能使用 Hot Reload。

工作原理

Hot Reload 只能在 Debug 模式下使用,是因為 Debug 模式下,F(xiàn)lutter 采用的是 JIT 動態(tài)編譯,代碼是運行在 Dart VM 上,JIT 將 Dart 編譯成可以運行在 Dart VM 上的 Dart Kernel,Dart Kernel 可以動態(tài)更新,所以就實現(xiàn)了代碼的實時更新功能。

當調用 Hot Reload 時:

  • 首先會掃描代碼,找到上次編譯之后有變化的 Dart 代碼。
  • 在將這些變化的 Dart 代碼轉化為增量的 Dart Kernel 文件。
  • 將增量的 Dart Kernel 文件發(fā)送到正在移動設備上運行的 Dart VM。
  • Dart VM 會將發(fā)來的增量 Dart Kernel 文件和原有的 Dart Kernel 文件合并,然后重新加載全新的 Dart Kernel。
  • 重新加載了 Dart Kernel,卻不會重新執(zhí)行代碼,而是通知 Flutter Framework 重建 Widget。

所以 Flutter 的 Hot Reload 并不會重新執(zhí)行一遍代碼,而是觸發(fā) Flutter 重新繪制,并且會保留 Flutter 之前的狀態(tài),所以 Hot Reload 也被稱為有狀態(tài)的熱重載。

不能使用 Hot Reload 的場景

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

1. 代碼更改會影響 APP 狀態(tài)的不能使用 Hot Reload

如果你的代碼更改會影響 APP 的狀態(tài),使得代碼更改之后的狀態(tài)和代碼更改之前的狀態(tài)不一樣,那么 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 會保留狀態(tài),在代碼更改之前,MyWidget 是 StatelessWidget ,將 StatelessWidget 改為 StatefulWidget ,如果 Hot Reload 成功,那么 MyWidget 會變成 StatefulWidget ,與它之前的狀態(tài)就會不兼容的,所以 Hot Reload 是不會成功的。

2. 全局變量( global variables)和靜態(tài)字段(static fields)的更改不能使用 Hot Reload

在 Flutter 中,全局變量和靜態(tài)字段被視為狀態(tài),因此在 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,是不會成功的,所以全局變量和靜態(tài)字段不能使用 Hot Reload。

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

因為 main() 方法不會因重建窗口小部件樹而重新執(zhí)行,所以更改 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. 枚舉類型更改為常規(guī)的類或者常規(guī)的類變?yōu)槊杜e類型也不能使用 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 可以完全重啟您的應用程序,但卻不用結束調試會話。這個特性可以用來快速調試代碼,對于業(yè)務代碼可能會出現(xiàn) Hot Restart 失敗的情況,這時直接 Hot Reload 也就是直接run就行了,Hot Restart 大部分使用場景還是用來調整UI或者業(yè)務代碼上小而不改變狀態(tài)的改動。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 前面已經(jīng)將 Flutter 運行起來了,然后打開 main.dart ,看到如下的代碼: 找到下面的代碼: 將這行...
    zhx喜籽閱讀 1,763評論 0 2
  • Hot Reload 的工作原理 Hot Reload 只能在 Debug 模式下使用,是因為 Debug 模式下...
    向上_d821閱讀 2,503評論 0 0
  • 一.別人給你私信時能看到的效果如下圖: 有兩種功能:1.鏈接別的地址(點擊百度會跳轉到百度頁面)。2.自動回復信...
    lvc閱讀 2,368評論 0 1
  • 過去的2017年,發(fā)生了許多事情,有好的,有不好的,不管怎樣都已經(jīng)過去了,只是希望2018年,我還能做最真的自已。...
    芯沫慕蕊閱讀 168評論 0 0
  • 簡書日記第31天 萬事開頭難 我喜歡閱讀,上小學時喜歡讀瓊瑤的作品,中學愛上了金庸的武俠小說,后來喜歡讀三毛、張愛...
    8bd6b4eb2e57閱讀 179評論 2 1

友情鏈接更多精彩內容