Hot Reload と Hot Restart を使って開発効率を上げていきましょう。
概要
Hot Reload と Hot Restart はプログラムの変更を即座に画面に反映させる機能であります。
Android と iOS のネイティブ開発言語にはこれらの機能はありません。
そのため、文章の一部変更など微々たる変更を加えただけでも、アプリを 0 からビルドする必要があり、長い待ち時間が発生してしまいます。
この 2 つの機能をマスターできれば、開発時間を大幅に削減することができるので、理解をしてどんどん活用していきましょう。
使用方法
ここでは、Android Studio を用いて、Hot Reload と Hot Restart の実行方法を説明していきます。
アプリのビルド方法によってそれぞれの実行方法は異なりますが、効果は全く同じです。
ターミナルで flutter run でビルドする場合
Android Studio のターミナルから flutter run
でアプリをビルドすると、ターミナル上には以下のログが表示されます。
このログに Hot Reload や Hot Restart のショートカットキーが記載されています。

そこで、マウスでターミナルをクリックしてフォーカスした状態で、キーボードの r
を押すと、Hot Reload が実行されます。

同様に、R (shift + r)
を押すと、 Hot Restart が実行されます。

Android Studio の GUI からビルドする場合
アプリを Android Studio の GUI (Graphic User Interface) ツールバーから起動した場合、同じツールバーに Hot Reload と Hot Restart ボタンを押せば実行できます。
ツールバーとは、以下の部分を指します。

稲妻のアイコンを押すと、Hot Reload が実行されます。

再生のアイコンを押すと、Hot Restart が実行されます。
また、Android Studio では、 スクリプトを保存する度に自動的に Hot Restart が実行されるように設定されています。
そのため、このアイコンを押さなくとも、保存する度に Hot Restart が実行されるということです。

両者の違い
Hot Reload と Hot Restart は共にコード変更を直ちに反映させられますが、その間には大きな違いがあります。
再ビルドの波及範囲
Hot Reload は Widget ツリーにある Widget の build()
関数のみを再実行して変化を反映させます。
その一方で、 Hot Restart は dart の main()
関数を再実行します。すべての .dart ファイルに定義されたグローバル変数とクラスにある static 変数をデフォルトの状態にします。
状態の保持
Hot Reload は Widget を生成する build()
関数のみを再実行するので、Widget の状態 (State) は保持されます。したがって、Hot Reload を "Stateful Reload" と考えてもいいでしょう。
しかし、Hot Restart はアプリ全体をゼロからビルドするので、各 Widget の状態を保持することはできません。
グローバル変数及び static 変数の更新
以下のように定義されたグローバル変数やあるクラスに定義されている static 変数に変更を加えた際に、Hot Restart を用いて変更を反映させる必要があります。
import 'package:flutter/material.dart';
const String globalString = 'グローバル変数';
class MyClass {
static const staticField = 'static変数';
}
void main(){
runApp(MyApp());
}
...
実例でその違いを理解しましょう
ここで、簡単な Flutter アプリを使って、Hot Reload と Hot Restart はそれぞれどの部分のコードが実行されるかを見て、両者の違いを理解していきましょう。
コードは以下のように、どの関数が実行されているかが分かるように、print()
を使用しています。
void main() {
print('in main()');
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('in MyApp build()');
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() {
print('in MyHomePage createState()');
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MyHomePage> {
int _counter;
@override
void initState() {
print('in _MyHomePageState initState()');
_counter = 0;
super.initState();
}
@override
Widget build(BuildContext context) {
print('in _MyHomePageState build()');
return Scaffold(
body: Center(
child: Text(
_counter.toString(),
),
),
);
}
}
以上のコードでアプリをビルドすると、次のログが返されます。
Running Gradle task 'assembleDebug'...
Running Gradle task 'assembleDebug'... Done 27.2s
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk... 6.6s
I/flutter (19765): in main()
I/flutter (19765): in MyApp build()
Waiting for Pixel 4a to report its views... 11ms
I/flutter (19765): in MyHomePage createState()
I/flutter (19765): in _MyHomePageState initState()
I/flutter (19765): in _MyHomePageState build()
Syncing files to device Pixel 4a... 276ms
この状態で、 Hot Reload すると、以下のログが返されます。
前述のように、Hot Reload は各 Widget の build 関数のみを再実行します。そして、main()
及び状態に関わる関数は実行されません。
Performing hot reload...
I/flutter (19765): in MyApp build()
I/flutter (19765): in _MyHomePageState build()
Reloaded 0 of 529 libraries in 147ms.
また、 Hot Restart をした場合、ログは以下のようになります。
Hot Reload と違って、
dart の main()
関数から実行されて、Widget の build()
に加えて initState()
のような状態関連の関数も再び実行されています。
つまり、アプリの状態は完全にデフォルトの状態にされています。
Performing hot restart...
Restarted application in 1,168ms.
I/flutter (19765): in main()
I/flutter (19765): in MyApp build()
I/flutter (19765): in MyHomePage createState()
I/flutter (19765): in _MyHomePageState initState()
I/flutter (19765): in _MyHomePageState build()
ビルド時間の比較
Hot Reload と Hot Restart の一番の利点は変化の反映時間を短縮できるところなので、どれくらい短縮できるかをここで比較してみました。
比較対象は、以下の 3 項目になります。
- アプリを 0 からビルドする
- Hot Reload
- Hot Restart
テストコードは、前の例で使用したものを使いました。
ビルド方法 | 1回目 | 2回目 | 3回目 |
---|---|---|---|
0 からビルド | 34s | 33s | 34s |
Hot Reload | 0.14s | 0.14s | 0.16s |
Hot Restart | 1.2s | 1.1s | 1.1s |
検証マシン:MacBook Pro, CPU : Intel Core i5, RAM : 16GB, macOS: Catalina 10.15.7
ビルドのスピードに関して、 Hot Reload と Hot Restart の方が圧倒的に早いことが一目瞭然です。
今回のテストコードのように単純なことしか処理しないアプリでも、 0 からビルドした場合には 30 秒程度かかります。
そのため、より複雑なアプリになればなるほど、Hot Reload と Hot Restart 機能の恩恵がどんどん大きくなります。