TOP(About this memo)) > 一覧(Flutter) > デバッグ
VSCodeのFlutter環境の構築
- Flutter extension for VS Codeを入れることでVSCode上でDevtoolsを使用可能となる。
- VSCode上で実行すると、自動的にDevtools上の出力を「DEBUG CONSOLE」へ出力する。
- VSCodeのインスペクタもVSCode上で開くことが可能。
- 「Run and Debug」パネルからDevtoolsのブレークポイントやログの設定ができる。
- Devtoolsに組み込まれたUIと異なり、リスタートしてもブレークポイントがリセットされない。
- IMO) DevtoolsのUIよりも高機能となっている。
- flutter runから起動する
flutter run
では内部的にDevtoolsを起動されていて、Dart DevToolsによるデバッグとパフォーマンス分析を有効になっている。
- 「v」でブラウザから開く
- (参考)Dartから起動する
- ブレークポイントを設定したい場合は、ソースコードに debugger() を設定して実行する。
- その後のステップ実行などはDevtools上で行う。
- gdbでブレークポイントを操作する方法もある(未確認)
- https://api.dart.dev/stable/3.1.1/dart-developer/dart-developer-library.html
- dart:developerパッケージをimportする。
- Dart ランタイムと対話することを目的とした特殊なライブラリ
- Dart Web および Dart Native (VM) のプラットフォーム固有の実装が含まれている。
- 開発モード(dart run)でのみ有効。
- 実稼働モード(dart compile exe)では動作しない。
- デバッガ(Devtool)前提の機能
dart run --observe
を実行して、Devtoolsを起動する。
- Dartコード内でブレークポイントを設定
- Dartコード内でログを出力
log()
- デバッガへログを送信する。
- 標準出力には出力されないため注意。
- その他機能は下記を参照。
- (参考)デバッガと Dart VMはどのように連携しているのか?
- (参考)Dart:developerのlogと、debugPrint、printの比較
- Dart:developer log
- デバッガへ送信
- Devtools上は表示されるがコマンドラインには表示されない。
- debugPrint
- print
- 引数の型はObject?型
- 記述すると警告が表示される。
- FlutterチームはVSCodeを推奨
If you write Flutter apps only with Dart code, you can debug your code using your IDE’s debugger. The Flutter team recommends VS Code.
様々なdebugフラグやメソッド
- https://docs.flutter.dev/testing/code-debugging
- 例えばエディタ上で”debug”と打つと様々なデバッグのグローバルなフラグやメソッドがレコメンドされる。
- これらのメソッドや、フラグをtrueにすることで様々な情報を確認する事ができる。
- 具体的にどの箇所で出力・実行されているかはFlutterのコードを読むと良い。
- スタックトレースを出力
- 階層構造の出力
- debugDumpApp()
- runApp()によって構成されるウィジェットの階層を出力
- 多くのFlutter標準のウィジェットはbuild()内で別のウィジェットやプライベートなウィジェットを生成する。
- これらのオブジェクトを目視で確認するために便利なメソッド
- debugDumpRenderTree()
- debugDumpLayerTree()
- Layerのツリーを出力。LayerはRenderObjectのツリーから生成された合成レイヤーである。
- debugDumpSemanticsTree();
- フレームやレンダリングパイプラインのデバッグ
- debugPrintBeginFrameBanner
- debugPrintEndFrameBanner = true;
- debugPrintRebuildDirtyWidgets
- Element.rebuild()のコールの度に対象のElementの情報が出力される
- コールバックを渡す方法もある: debugOnRebuildDirtyWidget
- debugPrintMarkNeedsLayoutStacks, debugPrintMarkNeedsPaintStacks
- RenderObject.markNeedsLayout()やmarkNeedsPaint()の際にデバッグメッセージを出力
- debugPrintBuildScope
- BuildOwner.BuildScope()が呼び出された際に出力
- debugPrintScheduleFrameStacks
- フレームのスケジューリングが行われた時にデバッグメッセージを出力
- UI上にデバッグ表示を表示
- debugPaintLayerBordersEnabled
- debugRepaintRainbowEnabled
- ※ 上記以外にも多くのフラグやメソッドがある。
flutter test の際の注意点
- Flutterのテストではデバッグ変数を有効にしている場合にassertエラーとなる。
- これを回避したい場合はテストの末尾でデバッグ変数にfalseに戻しておく必要がある。
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test:
The value of a widget debug variable was changed by the test.
DiagnosticableTree.toStringDeep()
main() => runApp(MyWidget());
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context) {
Future.microtask(
() => debugPrint((context as StatelessElement).toStringDeep()));
return const Placeholder();
}
}
// MyWidget
// └Placeholder
// └LimitedBox(maxWidth: 400.0, maxHeight: 400.0, renderObject: RenderLimitedBox#60f66)
// └CustomPaint(renderObject: RenderCustomPaint#af45e)
- WidgetもDiagnosticableTreeの派生クラスだが、試してみたところElementとは異なり、自身のクラス名のみ出力された。
- 参考
- この違いは、おそらくElementクラスがオーバーライドしているtoDiagnosticsNode()などが関係していると考えられる。
- TextTreeRenderer.render()が実際にStringを生成している箇所で、このあたりの実装を読めばわかるかもしれない。
パフォーマンス測定(未読)
アニメーションのデバッグ(未読)