Contents
Flutter デバッグ方法 — 優先順位付きワークフロー
優先順位付きワークフローは「短時間で切り分け→必要なら深掘り→報告・エスカレーション」の流れで進めると効率が良くなります。
ここでは各フェーズで行う具体的手順と、よくある失敗例と対処を短くまとめます。
短時間チェック(5–15分)
短時間チェックの目的は原因の一次切り分けです。まずは再現を固定し、環境とログを素早く取得します。
- 再現手順の固定(画面・操作・デバイス・時間帯・ネットワーク状態)
- 環境出力の保存
flutter doctor -v > flutter_doctor.txt
flutter devices # デバイスIDを確認
- ログの即時確認(例)
Linux / macOS:
flutter logs --device-id <id>
adb logcat -v time | grep -E 'flutter|Dart|AndroidRuntime'
Windows (PowerShell):
flutter logs --device-id <id>
adb logcat -v time | Select-String -Pattern 'flutter|Dart|AndroidRuntime'
iOS は Xcode のコンソールを参照
-
実行モードでの切り分け
flutter run -d <device_id> # debug
flutter run --profile -d <device_id> # profile(プロファイル計測)
flutter run --release -d <device_id> # release(最終検証) -
ホットリロード→ホットリスタート→フル再起動で差を確認(注意: ネイティブの変更はホットリロードで反映されない)
深掘りチェック(30–120分)
深掘りは DevTools や IDE のデバッガ、詳細ログで原因を特定します。profile モードでの計測が中心です。
- DevTools で Timeline(profile 推奨)と Memory を録る。問題操作を再現してから停止・解析する
- IDE で条件付きブレークポイントやログポイントを使って実行パスを追う
- 詳細ログの取得(標準的な例)
Bash:
flutter run -v > flutter_run_verbose.log 2>&1
PowerShell:
flutter run -v *> flutter_run_verbose.log
- ネイティブ層ログの収集(Android tombstone / iOS クラッシュログ)と、必要に応じたシンボル化準備
- 最小再現例の構築(UI とロジックを削ぎ落とした独立リポジトリで再現性を検証)
報告・エスカレーション
報告は再現性を担保することが重要です。環境情報とアーティファクトを揃えて共有する運用を推奨します。
- 最小再現例(Git リポジトリ)と再現手順(OS / デバイス / Flutter SDK / Channel)
- 取得アーティファクト(flutter_doctor, ログ抜粋, DevTools の timeline/memory ファイル, ビルドコマンド)
- ログやスクリーンショットに含まれる PII はマスクする運用ルール
- 優先度・影響度・暫定回避策を明記
バグ報告テンプレート(項目)
報告テンプレートは次の項目を含めるとトリアージが速くなります。
- タイトル(簡潔)
- 再現手順(ステップバイステップ)
- 環境情報(flutter doctor -v の該当部分、デバイス名、OS バージョン、Flutter SDK/Channel)
- 実行モード(debug / profile / release)
- 期待される挙動 / 実際の挙動(差分を明示)
- 最小再現コード(リポジトリリンク)
- 取得済みアーティファクト(ログ抜粋 / timeline / memory / build 設定)
- 一時回避策(あれば)
- 重要度(P0/P1/P2 等)
よくある失敗例と即効対応(短縮)
- Hot reload が反映しない → ネイティブ初期化や static 初期化の変更が原因の可能性、hot restart も効果薄ならフル再ビルド
- ログが不足 → verbose ログ(flutter run -v)を取得して差分確認
- 再現しない端末差 → デバイス固有のプラグイン差分をチェック
Flutter 実行モードと主要コマンド
実行モードの違いを正確に理解することが効果的なデバッグの前提です。各モードの特性に応じて計測・修正の手順を分けます。
モードの違いと使い分け
debug は Dart VM(JIT)で動作し、assert が有効でホットリロードが利用可能です。profile と release は AOT に近い実行で、パフォーマンス計測や最終検証に適しています。詳細は公式ドキュメントを参照すると相違点が明確になります(https://docs.flutter.dev/testing/build-modes)。
代表的なコマンド(実務例)
-
実行 / アタッチ
flutter devices
flutter run -d <device_id>
flutter run --profile -d <device_id>
flutter run --release -d <device_id>
flutter attach -d <device_id> -
ビルド(例)
flutter build apk --release
flutter build ios --release # アーカイブは Xcode と連携
flutter build apk --release --obfuscate --split-debug-info=./debug-info/<version> -
ログ / 詳細出力
flutter logs --device-id <id>
flutter run -v > verbose.log 2>&1 # Bash
flutter run -v *> verbose.log # PowerShell
ホットリロード/ホットリスタートの挙動
ホットリロードは主に debug(JIT)で有効で、State オブジェクトを保持してコード差分を注入する機能です。ネイティブ側の変更や global 初期化の変更は反映されない点に注意します。profile / release モードではホットリロードは基本的に使えないため、プロファイリングは profile ビルドで計測することが前提です。
シンボル化とビルドフラグ(運用上の注意)
- obfuscate と --split-debug-info の組合せでスタックトレースの復号に必要な debug-info を生成
flutter build apk --release --obfuscate --split-debug-info=./debug-info/<version>
flutter symbolize --debug-info=./debug-info/<version> < raw_trace.txt > symbolized.txt
- Android の R8 mapping.txt、iOS の dSYM もリリースごとに保管・アップロードが必須
- debug-info や mapping を公開リポジトリに置かないこと、CI での自動アップロードや機密ストレージ保管を推奨(アップロード先の認証情報は安全に管理すること)
公式の obfuscation / symbolization の解説: https://docs.flutter.dev/deployment/obfuscate
IDE / DevTools とプラットフォーム別手順
IDE と DevTools を組合せると再現→解析→修正の流れがスムーズになります。プラットフォーム固有のログ取得方法も併せて整理します。
IDE での基本操作
IDE 上ではブレークポイント、条件付きブレークポイント、ログポイントを使って実行パスを確認します。式評価でオブジェクトの中身を調べ、アタッチで既存プロセスに接続する運用が一般的です。
- ブレークポイント(通常 / 条件付き / ログポイント)
- Evaluate Expression(副作用を避けて利用)
- ステップ実行(Step Over / Into / Out)
- アタッチ設定(Android Studio: Run → Attach to Process、VS Code の launch.json)
DevTools の主要機能と使い分け
DevTools は問題のタイプに応じて使い分けます。Timeline はフレーム単位の遅延解析、Memory はヒープスナップショットとアロケーション解析に有効です。profile モードで Timeline を取得するのが望ましい運用です(https://docs.flutter.dev/development/tools/devtools/overview)。
- Inspector:ウィジェットツリーとプロパティ確認
- Timeline / CPU:フレームの重さ・コールスタック特定(sampling / instrumentation の違いに注意)
- Memory:ヒープスナップショット、allocation profile、参照グラフ
- Isolates:複数 isolate のスタック確認・一時停止
Android の手順と留意点
- ログ取得: adb logcat / flutter logs
- ネイティブクラッシュ: tombstone の確認、NDK クラッシュはシンボル化(ndk-stack 等)
- ビルド不整合対策: flutter clean → flutter pub get、Gradle/NDK のバージョン確認、プラグインのネイティブ実装差分確認
iOS の手順と留意点
- ログ取得: Xcode コンソール、Devices and Simulators のログ
- dSYM の管理: リリースごとに dSYM を保存・クラッシュレポートサービスへアップロード
- Pod 周り: ios フォルダでの pod install / pod update が必要な場合あり
Web の手順と留意点
- 開発: flutter run -d chrome と Chrome DevTools の連携
- 本番: source map を利用して Dart ソースにマップして解析
- Web 固有の指標: スクリプト実行時間、DOM 描画の影響
Desktop の手順と留意点
- 標準出力 / 標準エラーのファイル出力が容易
- Windows の Event Viewer / macOS Console などプラットフォームログを併用
よくある失敗例と即効対応(IDE / プラットフォーム)
- attach が失敗 → デバイス ID の不一致やポート競合の確認、flutter devices の再確認
- Xcode が古い Pod を使用 → ios フォルダで pod install / Podfile.lock の確認
- source map が見つからない(Web)→ ビルド設定で source map 出力を確認
ログ設計・UI とパフォーマンス診断
ログ設計と UI の解析手順を定めると初動対応が速くなります。ログレベル設計と PII マスクは運用要件として必須です。
ログ出力と設計
短く分かりやすいログ設計が調査効率を上げます。開発時と本番で出力レベルを切り替える仕組みを用意します。
- print:手早い確認用(長い文字列は切れることあり)
-
debugPrint:長い出力を安全に扱う
dart
debugPrint(largeString, wrapWidth: 1024); -
package:logging:環境ごとのログレベル切替やハンドラ制御に有用
dart
import 'package:logging/logging.dart';
final _logger = Logger('app');
void main() {
Logger.root.level = Level.INFO;
Logger.root.onRecord.listen((rec) {
print('${rec.level.name}: ${rec.time}: ${rec.loggerName}: ${rec.message}');
});
_logger.info('App started');
runApp(MyApp());
}
- ログのフィルタリング(実務例)
- flutter logs --device-id
- adb logcat -v time | grep/Select-String で flutter/Dart を抽出
- ログ設計の方針: ログレベル基準、PII のマスク、本番で詳細ログを残さない仕組み
UI/レイアウト診断
UI の崩れやオーバーフローは再現とツリー解析で原因を特定します。
- Inspector でウィジェットツリーとプロパティを確認
-
デバッグでレイアウト境界を可視化(デバッグ専用)
dart
import 'package:flutter/rendering.dart';
void main() {
debugPaintSizeEnabled = true;
runApp(MyApp());
}
(リリースに残さない運用が前提) -
RenderFlex overflow の典型的原因と対応
- 子が大きすぎる → SingleChildScrollView / Flexible / Expanded
- 無限高さの親 → SizedBox / ConstrainedBox を使う
パフォーマンス診断と最適化ヒント
パフォーマンス改善は「原因特定→仮説→最小再現→効果測定」のサイクルが重要です。
- Profile モードで Timeline を取得してボトルネック特定
- sampling と instrumentation の使い分け(負荷と詳細度のトレードオフ)
- 最適化の基本:
- const コンストラクタの活用
- RepaintBoundary の適切な設置
- 画像はサーバ側でリサイズ、キャッシュ活用(CachedNetworkImage 等)
- 重い処理は build の外へ移す(compute / isolate)
よくある失敗例と即効対応(UI / パフォーマンス)
- jank(フレーム落ち)が発生 → Timeline でどのフレームが重いか特定し、build/layout/paint のいずれがボトルネックか切り分け
- 画像読み込みで大量メモリ → サムネイル化 / サイズ制限 / キャッシュの導入
メモリ・クラッシュ解析と運用フロー
本番でのメモリ増加やクラッシュ対応は運用フローを整備することで復旧と原因究明が早くなります。シンボル管理と CI 連携は運用上の重要ポイントです。
メモリリーク解析の手順
メモリ解析はスナップショットの差分を中心に進めます。
- ベースラインスナップショットの取得
- 問題操作を実行して再スナップショット取得
- 差分比較で増加しているクラスを特定
- 参照グラフでルートから何が保持しているか確認
- よくある原因と対処例
- StreamSubscription / Timer / AnimationController の未解放 → dispose で cancel/dispose
- 大きな画像の連続読み込み → サイズ削減・キャッシュ制御
- グローバルキャッシュの無制限使用 → 上限設定
例: dispose の基本形
|
1 2 3 4 5 6 7 |
@override void dispose() { _subscription?.cancel(); _controller.dispose(); super.dispose(); } |
クラッシュ収集とシンボル化(運用上の注意)
クラッシュ解析ではシンボル化が不可欠です。運用では debug-info / mapping / dSYM の取り扱い規程を整備します。
-
ビルド時の例(Android AAB/APK)
flutter build apk --release --obfuscate --split-debug-info=./debug-info/<version> -
スタックトレースの復号
flutter symbolize --debug-info=./debug-info/<version> < raw_trace.txt > symbolized.txt -
Android の R8 mapping、iOS の dSYM もリリースごとに保管・アップロード
- 運用上の注意点:
- debug-info を公開リポジトリに置かない(秘匿ストレージで管理)
- CI で自動アップロードする場合はアップロード先の認証情報を安全に管理(キー管理、ローテーション)
- クラッシュレポートに PII が含まれないルールを運用で徹底
CI とアーティファクト管理の実務フロー(例)
- ビルド: --split-debug-info で debug-info を生成
- アップロード: CI で Crashlytics/Sentry 等へ debug symbols をアップロード
- 保管: debug-info / mapping / dSYM を機密アーティファクトストレージに保存(アクセス制限)
- モニタリング: 自動通知 → 初期トリアージ → 最小再現例作成 → 修正 → 回帰検証
よくある失敗例と即効対応(メモリ/クラッシュ)
- シンボル未アップロードによりスタックが読めない → 対象リリースの debug-info/mapping を検索・アップロード
- 誤って debug-info を公開リポジトリへ配置 → アクセス権の取り消しとキーのローテーション
- クラッシュレポートに機密情報が含まれる → 収集前にマスクフィルタを適用
Flutter デバッグ方法まとめ
ここまでの要点を短く整理します。日常運用で再現→ログ取得→モード差分→最小再現→報告の流れを確立すると対応速度が向上します。
- 再現手順と環境情報を最初に固定する(flutter doctor の出力保管)
- まず短時間チェック(ログ確認・実行モード切替・hot reload/ restart の確認)
- Deep ダイブは DevTools(Timeline/Memory)と IDE のブレークポイントで行い、profile モードで性能測定
- クラッシュ対応では debug symbols / mapping / dSYM の運用ルールと CI アップロードを整備
- ログ設計で PII マスクと出力レベル運用を決め、プロダクションに詳細ログを残さない
以上が現場で使える Flutter デバッグ方法 の主要ポイントです。繰り返し実施可能なチェックリストと、最小再現例の用意を優先するとトリアージと修正が速くなります。