Flutterアプリを開発していると、設定変更やアップデート後にアプリを再起動したいケースがあります。
例えば、
- テーマ変更を反映する
- 言語変更を反映する
- 動的アップデート後にアプリを再起動する
- アプリの状態を完全にリセットする
- キャッシュやアプリデータを削除する
- ログアウト時にデータをクリアする
などです。
通常のFlutterアプリでは、Widgetを再構築することでUIを更新できますが、アプリそのものを再起動したい場合には、より踏み込んだ処理が必要になります。
今回紹介する terminate_restart は、Flutterアプリの終了・再起動とデータクリアをまとめて扱えるプラグインです。
UIだけを再構築する軽量な再起動から、プロセスを完全に終了して再起動する方法まで用意されており、Android・iOS・Webに対応しています。
この記事では、terminate_restart の基本的な使い方から、UIのみの再起動、完全なアプリ再起動、確認ダイアログ、データクリア、KeychainやUserDefaultsの保持まで詳しく解説します。
- terminate_restartとは?
- terminate_restartの特徴
- インストール
- 初期化する
- UIだけを再起動する
- 完全にアプリを再起動する
- UI再起動と完全再起動の違い
- 確認ダイアログを表示する
- 確認ダイアログをカスタマイズする
- アプリデータを削除する
- Keychainを保持する
- UserDefaultsを保持する
- データをクリアしながら再起動する
- 設定変更後の再起動
- 動的アップデート後に利用する
- ログアウト時のデータクリア
- Webにも対応
- AndroidではActivityを再作成する
- iOSでの再起動
- iOSのInfo.plistを設定する
- TerminateRestartOptions
- restartApp
- restartAppWithConfirmation
- パフォーマンス
- セキュリティ面での注意
- 注意点
- メリット
- まとめ
terminate_restartとは?
terminate_restart は、Flutterアプリの再起動や終了を実装するためのプラグインです。
大きく分けると、
UIのみ再起動
↓
Widgetツリーを再構築
完全再起動
↓
アプリプロセスを終了
↓
アプリを再起動
という2種類の使い方ができます。
さらに、再起動時にアプリデータを削除したり、重要なデータだけを保持したりすることもできます。
terminate_restartの特徴
主な特徴は以下の通りです。
| 機能 | 対応 |
|---|---|
| UIのみ再起動 | ○ |
| 完全なアプリ再起動 | ○ |
| 確認ダイアログ | ○ |
| アプリデータ削除 | ○ |
| Keychain保持 | ○ |
| UserDefaults保持 | ○ |
| Android | ○ |
| iOS | ○ |
| Web | ○ |
| WebのStorage削除 | ○ |
| カスタム確認メッセージ | ○ |
UIのみの再起動では、アプリを完全に終了させずにWidgetツリーを再構築できます。
一方、完全再起動ではアプリプロセスの終了と再起動を行います。
インストール
pubspec.yaml に追加します。
YAML
dependencies:
terminate_restart: ^1.1.0
または、以下のコマンドでも追加できます。
Bash
flutter pub add terminate_restart
コードから利用する場合は、
Dart
import 'package:terminate_restart/terminate_restart.dart';
をインポートします。
初期化する
アプリ起動時にプラグインを初期化します。
Dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
TerminateRestart.instance.initialize();
runApp(
TerminateRestart.wrapWithRestart(
child: const MyApp(),
),
);
}
wrapWithRestart() は、UIのみの再起動を利用する場合に重要です。
アプリ全体をこのWidgetでラップすることで、terminate: false の再起動時にWidgetツリー全体を適切に再構築できます。
UIだけを再起動する
まずはアプリプロセスを終了せず、UIだけを更新する方法です。
Dart
await TerminateRestart.instance.restartApp(
options: const TerminateRestartOptions(
terminate: false,
),
);
terminate を false にすると、完全なプロセス終了ではなくUIの再構築として処理されます。
例えば、
- テーマ変更
- 言語変更
- UI設定変更
などを反映したい場合に利用できます。
完全にアプリを再起動する
アプリプロセスを終了して再起動したい場合は、terminate を true にします。
Dart
await TerminateRestart.instance.restartApp(
options: const TerminateRestartOptions(
terminate: true,
),
);
これにより、完全なアプリ終了と再起動を行います。
UIだけを更新する方法とは異なり、アプリを新しい状態から起動し直したい場合に向いています。
UI再起動と完全再起動の違い
2つの方法を比較すると、
| 方法 | terminate | 特徴 |
|---|---|---|
| UI再起動 | false | UIを素早く再構築 |
| 完全再起動 | true | アプリプロセスを終了して再起動 |
となります。
UI再起動は軽量なため、
設定変更
↓
UI再構築
のような用途に向いています。
完全再起動は、
アップデート
↓
アプリ終了
↓
再起動
のようなケースに向いています。
確認ダイアログを表示する
ユーザーに確認してから再起動することもできます。
Dart
await TerminateRestart.instance.restartAppWithConfirmation(
context,
title: 'Restart App',
message: 'Do you want to restart the app?',
terminate: true,
);
ユーザーが確認すると再起動し、キャンセルすると何もせずに終了します。
確認ダイアログをカスタマイズする
タイトルやメッセージだけでなく、ボタンのテキストも変更できます。
Dart
await TerminateRestart.instance.restartAppWithConfirmation(
context,
title: 'アップデート完了',
message: '変更を反映するためアプリを再起動します。',
confirmText: '再起動する',
cancelText: 'あとで',
terminate: true,
);
ユーザー向けの設定画面などに組み込みやすいAPIになっています。
アプリデータを削除する
再起動時にアプリデータを削除することもできます。
Dart
await TerminateRestart.instance.restartApp(
options: const TerminateRestartOptions(
terminate: true,
clearData: true,
),
);
clearData を true にすると、再起動時にデータのクリアを実行します。
例えば、
- キャッシュ削除
- ログアウト
- アプリ状態のリセット
などに利用できます。
Keychainを保持する
iOSでは、データを削除しながらKeychainのデータを保持する設定も用意されています。
Dart
await TerminateRestart.instance.restartApp(
options: const TerminateRestartOptions(
terminate: true,
clearData: true,
preserveKeychain: true,
),
);
認証情報など、アプリデータをクリアしても保持したい情報がある場合に利用できます。
UserDefaultsを保持する
UserDefaultsを保持することもできます。
Dart
await TerminateRestart.instance.restartApp(
options: const TerminateRestartOptions(
terminate: true,
clearData: true,
preserveUserDefaults: true,
),
);
設定情報などを残したまま、その他のアプリデータをクリアしたい場合に便利です。
データをクリアしながら再起動する
例えば、重要な設定を保持しながらデータを削除する場合は、
Dart
await TerminateRestart.instance.restartApp(
options: const TerminateRestartOptions(
terminate: true,
clearData: true,
preserveKeychain: true,
preserveUserDefaults: true,
),
);
という構成にできます。
これはログアウト処理やアプリ状態のリセットなどに利用できます。
設定変更後の再起動
アプリの設定を変更した後、再起動が必要になるケースがあります。
例えば、
言語変更
↓
設定保存
↓
アプリ再起動
↓
新しい言語で起動
という処理です。
軽量なUI再起動なら、
Dart
await TerminateRestart.instance.restartApp(
options: const TerminateRestartOptions(
terminate: false,
),
);
とできます。
UI-only restartは、テーマ変更や言語変更などの用途が想定されています。
動的アップデート後に利用する
動的に新しいアセットなどを取得した後、再起動して変更を反映したいケースにも利用できます。
例えば、
Dart
await TerminateRestart.instance.restartAppWithConfirmation(
context,
title: 'Update Ready',
message: 'Restart to apply updates?',
terminate: true,
);
のように、アップデート完了後に確認ダイアログを表示できます。
ログアウト時のデータクリア
ログアウト時にユーザー固有のデータを削除し、アプリを初期状態に戻したい場合にも利用できます。
例えば、
ログアウト
↓
ユーザーデータ削除
↓
必要な認証情報は保持
↓
アプリ再起動
という流れを作れます。
ただし、どのデータを削除するかについては、アプリの認証設計やセキュリティ要件に合わせて慎重に決める必要があります。
Webにも対応
terminate_restart はWebにも対応しています。
Webでは、アプリプロセスをネイティブアプリと同じように終了するのではなく、ページのリロードによって再起動を実現します。
さらに、データクリアを指定した場合は、
- localStorage
- sessionStorage
- Cookies
- IndexedDB
- Cache API
などのブラウザストレージも対象になります。
そのため、Flutter Webでもアプリをリフレッシュする用途に利用できます。
AndroidではActivityを再作成する
AndroidのUI-only restartでは、Activityの再作成が利用されています。
内部では、
currentActivity.recreate();
という仕組みによってUIを再構築します。
完全再起動ではプロセス終了とIntentによる再起動を組み合わせています。
アプリを完全に作り直すのではなく、用途に応じてUI再構築とプロセス再起動を使い分けられるのが特徴です。
iOSでの再起動
iOSではAndroidとは異なり、アプリの終了や再起動に関してOS側の制約があります。
terminate_restart では、iOS向けにシステムのルールを考慮した仕組みが用意されています。
また、iOSで再起動機能を利用するには、Info.plist にURL Schemeの設定が必要です。パッケージではBundle Identifierを利用したURL Schemeを設定する形になっています。
iOSのInfo.plistを設定する
iOSで再起動機能を利用する場合は、ios/Runner/Info.plist にURL Schemeを追加します。
XML
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
<key>CFBundleURLName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</dict>
</array>
この設定によって、プラグインがBundle Identifierを使ってアプリを再起動できるようになります。
TerminateRestartOptions
再起動の動作は TerminateRestartOptions で設定します。
主なパラメータは以下の通りです。
| パラメータ | 型 | デフォルト | 内容 |
|---|---|---|---|
terminate | bool | true | プロセスを完全終了するか |
clearData | bool | false | アプリデータを削除するか |
preserveKeychain | bool | false | Keychainを保持するか |
preserveUserDefaults | bool | false | UserDefaultsを保持するか |
特に terminate と clearData は動作への影響が大きいため、用途に応じて適切に設定する必要があります。
restartApp
restartApp は確認なしですぐに再起動を実行するAPIです。
Dart
Future<bool> restartApp({
required TerminateRestartOptions options,
})
成功すると true が返されます。
例えば、
Dart
final result =
await TerminateRestart.instance.restartApp(
options: const TerminateRestartOptions(
terminate: false,
),
);
print(result);
のように利用できます。
restartAppWithConfirmation
ユーザーへの確認を挟みたい場合は restartAppWithConfirmation を利用します。
Dart
final result =
await TerminateRestart.instance
.restartAppWithConfirmation(
context,
title: 'Restart Required',
message: 'The app needs to restart.',
confirmText: 'Restart Now',
cancelText: 'Later',
terminate: true,
);
ユーザーが再起動を選択した場合は成功結果が返され、キャンセルした場合は false が返ります。
パフォーマンス
パッケージのドキュメントでは、再起動方式ごとの目安として、
| 操作 | 平均時間 |
|---|---|
| UI-only Restart | 約300ms |
| Full Termination | 約800ms |
| Data Clearing | 約200ms |
| Confirmation Dialog | +約100ms |
とされています。
ただし、これらはあくまでパッケージ側が示している目安であり、実際の処理時間はデバイスやアプリの状態などによって変わります。
セキュリティ面での注意
アプリデータの削除機能を利用する場合は、データの種類を意識する必要があります。
例えば、
- 認証情報
- アクセストークン
- 生体認証関連の状態
- ユーザー設定
- キャッシュ
などです。
特に認証情報を扱う場合は、Keychainなどの安全なストレージを利用し、ログアウト時にどの情報を削除・保持するかを明確に設計することが重要です。
注意点
アプリの再起動は必要な場合だけ利用する
単純なUI更新であれば、通常のFlutterのState更新やWidget再構築で十分です。
アプリ全体を再起動するとユーザー体験に影響するため、必要な場面でのみ利用するのがおすすめです。
clearData の利用には注意する
clearData: true にするとアプリデータの削除が発生するため、ユーザーが必要としている設定や認証情報まで消してしまわないように設計する必要があります。
iOSでは追加設定が必要
iOSの再起動機能を利用する場合、Info.plist のURL Scheme設定が必要です。
UI-only restartにはラッパーが必要
terminate: false のUI再起動を適切に利用するには、TerminateRestart.wrapWithRestart() でアプリをラップする必要があります。
プラットフォームごとの挙動が異なる
Android、iOS、Webではアプリのライフサイクルや再起動方法が異なります。
そのため、実際のアプリでは各プラットフォームで動作確認することが重要です。
メリット
UI再起動と完全再起動を使い分けられる
単純なUI更新からプロセス終了まで、用途に応じて選択できます。
データクリアにも対応
再起動と同時にアプリデータをクリアできます。
データ保持を細かく設定できる
KeychainやUserDefaultsを保持する設定が用意されています。
確認ダイアログを標準搭載
ユーザーに確認してから再起動する処理を簡単に実装できます。
Android・iOS・Webに対応
ネイティブアプリだけでなくFlutter Webでも利用できます。
まとめ
terminate_restart は、Flutterアプリの再起動・終了・データクリアをまとめて扱えるプラグインです。
単純にアプリを再起動するだけではなく、
- UI-only Restart
- Full Process Restart
- 確認ダイアログ
- アプリデータクリア
- Keychain保持
- UserDefaults保持
- Webページリロード
- ブラウザストレージ削除
など、細かな制御ができる点が特徴です。
特に、
設定変更
↓
UI再構築
アップデート
↓
完全再起動
ログアウト
↓
データクリア
↓
再起動
といったアプリライフサイクルを実装したい場合に便利でしょう。
一方で、アプリの再起動やデータ削除はユーザー体験やデータ管理に大きく影響するため、必要以上に利用するのではなく、通常のWidget再構築や状態管理で対応できないケースに利用するのがおすすめです。
Flutterアプリで「UIを再構築したい」「アプリを完全に再起動したい」「データをクリアして初期状態に戻したい」といった要件がある場合に、候補として覚えておきたいパッケージです。
