<

Flutter アプリをプログラムでデバッグする

このドキュメントでは、コードで有効にできるデバッグ機能について説明します。 デバッグおよびプロファイリング ツールの完全なリストについては、デバッグページ。

ロギング

アプリケーションのログ記録には 2 つのオプションがあります。 1つ目は、使用することですstdoutstderr。 一般に、これは次を使用して行われますprint()ステートメント、 または輸入することでdart:ioそしてメソッドを呼び出すstderrstdout。例えば:

stderr.writeln('print me');

一度に大量に出力すると、Android が時々 いくつかのログ行を破棄します。これを回避するには、次を使用しますdebugPrint()、 flutterズからfoundation図書館。これはラッパーアラウンドですprint出力が低下しないレベルまで出力を抑制します。 Androidのカーネル。

アプリケーションログのもう 1 つのオプションは、dart:developer log()関数。これにより、 ログ出力の粒度と情報がもう少し詳しくなります。 以下に例を示します。

import 'dart:developer' as developer;

void main() {
  developer.log('log me', name: 'my.app.category');

  developer.log('log me 1', name: 'my.other.category');
  developer.log('log me 2', name: 'my.other.category');
}

アプリケーション データをログ呼び出しに渡すこともできます。 このための規則では、error:名前付き のパラメータlog()呼び出し、オブジェクトを JSON エンコードする 送信したいものを選択し、エンコードされた文字列を エラーパラメータ。

import 'dart:convert';
import 'dart:developer' as developer;

void main() {
  var myCustomObject = MyCustomObject();

  developer.log(
    'log me',
    name: 'my.app.category',
    error: jsonEncode(myCustomObject),
  );
}

DevTool のログ ビューでログ出力を表示する場合は、 JSON エンコードされたエラー パラメータはデータ オブジェクトとして解釈されます そして、そのログ エントリの詳細ビューにレンダリングされます。

ブレークポイントの設定

プログラムによるブレークポイントを挿入するには、debugger()声明。これを使用するには、次のことを行う必要があります をインポートするdart:developer上部のパッケージ 関連するファイル。

debugger()ステートメントはオプションを取りますwhen次の場合にのみ中断するように指定できる引数 次の例のように、特定の条件が true です。

import 'dart:developer';

void someFunction(double offset) {
  debugger(when: offset > 30);
  // ...
}

デバッグ フラグ: アプリケーション層

Flutter フレームワークの各層は、その層をダンプする機能を提供します。 現在の状態またはイベントをコンソールに送信します (使用debugPrint)。

ウィジェットツリー

ウィジェット ライブラリの状態をダンプするには、次の呼び出しを行います。debugDumpApp()。 アプリケーションが実行されていないときは、多かれ少なかれこれをいつでも呼び出すことができます。 ビルドフェーズの実行中 (つまり、ビルドフェーズ内のどこにもありません)build()メソッド)、アプリが少なくとも 1 回ビルドされており、デバッグ モードにある場合 (つまり、電話をかけた後はいつでもrunApp())。

たとえば、次のようなアプリケーションです。

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: AppHome(),
    ),
  );
}

class AppHome extends StatelessWidget {
  const AppHome({super.key});

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: TextButton(
          onPressed: () {
            debugDumpApp();
          },
          child: const Text('Dump App'),
        ),
      ),
    );
  }
}

前のアプリは次のような出力を行います (正確な詳細はフレームワークのバージョンによって異なります。 デバイスのサイズなど):

I/flutter ( 6559): WidgetsFlutterBinding - CHECKED MODE
I/flutter ( 6559): RenderObjectToWidgetAdapter<RenderBox>([GlobalObjectKey RenderView(497039273)]; renderObject: RenderView)
I/flutter ( 6559): └MaterialApp(state: _MaterialAppState(1009803148))
I/flutter ( 6559):  └ScrollConfiguration()
I/flutter ( 6559):   └AnimatedTheme(duration: 200ms; state: _AnimatedThemeState(543295893; ticker inactive; ThemeDataTween(ThemeData(Brightness.light Color(0xff2196f3) etc...) → null)))
I/flutter ( 6559):    └Theme(ThemeData(Brightness.light Color(0xff2196f3) etc...))
I/flutter ( 6559):     └WidgetsApp([GlobalObjectKey _MaterialAppState(1009803148)]; state: _WidgetsAppState(552902158))
I/flutter ( 6559):      └CheckedModeBanner()
I/flutter ( 6559):       └Banner()
I/flutter ( 6559):        └CustomPaint(renderObject: RenderCustomPaint)
I/flutter ( 6559):         └DefaultTextStyle(inherit: true; color: Color(0xd0ff0000); family: "monospace"; size: 48.0; weight: 900; decoration: double Color(0xffffff00) TextDecoration.underline)
I/flutter ( 6559):          └MediaQuery(MediaQueryData(size: Size(411.4, 683.4), devicePixelRatio: 2.625, textScaleFactor: 1.0, padding: EdgeInsets(0.0, 24.0, 0.0, 0.0)))
I/flutter ( 6559):           └LocaleQuery(null)
I/flutter ( 6559):            └Title(color: Color(0xff2196f3))
I/flutter ( 6559):             └Navigator([GlobalObjectKey<NavigatorState> _WidgetsAppState(552902158)]; state: NavigatorState(240327618; tracking 1 ticker))
I/flutter ( 6559):              └Listener(listeners: down, up, cancel; behavior: defer-to-child; renderObject: RenderPointerListener)
I/flutter ( 6559):               └AbsorbPointer(renderObject: RenderAbsorbPointer)
I/flutter ( 6559):                └Focus([GlobalKey 489139594]; state: _FocusState(739584448))
I/flutter ( 6559):                 └Semantics(container: true; renderObject: RenderSemanticsAnnotations)
I/flutter ( 6559):                  └_FocusScope(this scope has focus; focused subscope: [GlobalObjectKey MaterialPageRoute<void>(875520219)])
I/flutter ( 6559):                   └Overlay([GlobalKey 199833992]; state: OverlayState(619367313; entries: [OverlayEntry@248818791(opaque: false; maintainState: false), OverlayEntry@837336156(opaque: false; maintainState: true)]))
I/flutter ( 6559):                    └_Theatre(renderObject: _RenderTheatre)
I/flutter ( 6559):                     └Stack(renderObject: RenderStack)
I/flutter ( 6559):                      ├_OverlayEntry([GlobalKey 612888877]; state: _OverlayEntryState(739137453))
I/flutter ( 6559):                      │└IgnorePointer(ignoring: false; renderObject: RenderIgnorePointer)
I/flutter ( 6559):                      │ └ModalBarrier()
I/flutter ( 6559):                      │  └Semantics(container: true; renderObject: RenderSemanticsAnnotations)
I/flutter ( 6559):                      │   └GestureDetector()
I/flutter ( 6559):                      │    └RawGestureDetector(state: RawGestureDetectorState(39068508; gestures: tap; behavior: opaque))
I/flutter ( 6559):                      │     └_GestureSemantics(renderObject: RenderSemanticsGestureHandler)
I/flutter ( 6559):                      │      └Listener(listeners: down; behavior: opaque; renderObject: RenderPointerListener)
I/flutter ( 6559):                      │       └ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox)
I/flutter ( 6559):                      └_OverlayEntry([GlobalKey 727622716]; state: _OverlayEntryState(279971240))
I/flutter ( 6559):                       └_ModalScope([GlobalKey 816151164]; state: _ModalScopeState(875510645))
I/flutter ( 6559):                        └Focus([GlobalObjectKey MaterialPageRoute<void>(875520219)]; state: _FocusState(331487674))
I/flutter ( 6559):                         └Semantics(container: true; renderObject: RenderSemanticsAnnotations)
I/flutter ( 6559):                          └_FocusScope(this scope has focus)
I/flutter ( 6559):                           └Offstage(offstage: false; renderObject: RenderOffstage)
I/flutter ( 6559):                            └IgnorePointer(ignoring: false; renderObject: RenderIgnorePointer)
I/flutter ( 6559):                             └_MountainViewPageTransition(animation: AnimationController(⏭ 1.000; paused; for MaterialPageRoute<void>(/))➩ProxyAnimation➩Cubic(0.40, 0.00, 0.20, 1.00)➩Tween<Offset>(Offset(0.0, 1.0) → Offset(0.0, 0.0))➩Offset(0.0, 0.0); state: _AnimatedState(552160732))
I/flutter ( 6559):                              └SlideTransition(animation: AnimationController(⏭ 1.000; paused; for MaterialPageRoute<void>(/))➩ProxyAnimation➩Cubic(0.40, 0.00, 0.20, 1.00)➩Tween<Offset>(Offset(0.0, 1.0) → Offset(0.0, 0.0))➩Offset(0.0, 0.0); state: _AnimatedState(714726495))
I/flutter ( 6559):                               └FractionalTranslation(renderObject: RenderFractionalTranslation)
I/flutter ( 6559):                                └RepaintBoundary(renderObject: RenderRepaintBoundary)
I/flutter ( 6559):                                 └PageStorage([GlobalKey 619728754])
I/flutter ( 6559):                                  └_ModalScopeStatus(active)
I/flutter ( 6559):                                   └AppHome()
I/flutter ( 6559):                                    └Material(MaterialType.canvas; elevation: 0; state: _MaterialState(780114997))
I/flutter ( 6559):                                     └AnimatedContainer(duration: 200ms; has background; state: _AnimatedContainerState(616063822; ticker inactive; has background))
I/flutter ( 6559):                                      └Container(bg: BoxDecoration())
I/flutter ( 6559):                                       └DecoratedBox(renderObject: RenderDecoratedBox)
I/flutter ( 6559):                                        └Container(bg: BoxDecoration(backgroundColor: Color(0xfffafafa)))
I/flutter ( 6559):                                         └DecoratedBox(renderObject: RenderDecoratedBox)
I/flutter ( 6559):                                          └NotificationListener<LayoutChangedNotification>()
I/flutter ( 6559):                                           └_InkFeature([GlobalKey ink renderer]; renderObject: _RenderInkFeatures)
I/flutter ( 6559):                                            └AnimatedDefaultTextStyle(duration: 200ms; inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 400; baseline: alphabetic; state: _AnimatedDefaultTextStyleState(427742350; ticker inactive))
I/flutter ( 6559):                                             └DefaultTextStyle(inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 400; baseline: alphabetic)
I/flutter ( 6559):                                              └Center(alignment: Alignment.center; renderObject: RenderPositionedBox)
I/flutter ( 6559):                                               └TextButton()
I/flutter ( 6559):                                                └MaterialButton(state: _MaterialButtonState(398724090))
I/flutter ( 6559):                                                 └ConstrainedBox(BoxConstraints(88.0<=w<=Infinity, h=36.0); renderObject: RenderConstrainedBox relayoutBoundary=up1)
I/flutter ( 6559):                                                  └AnimatedDefaultTextStyle(duration: 200ms; inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 500; baseline: alphabetic; state: _AnimatedDefaultTextStyleState(315134664; ticker inactive))
I/flutter ( 6559):                                                   └DefaultTextStyle(inherit: false; color: Color(0xdd000000); family: "Roboto"; size: 14.0; weight: 500; baseline: alphabetic)
I/flutter ( 6559):                                                    └IconTheme(color: Color(0xdd000000))
I/flutter ( 6559):                                                     └InkWell(state: _InkResponseState<InkResponse>(369160267))
I/flutter ( 6559):                                                      └GestureDetector()
I/flutter ( 6559):                                                       └RawGestureDetector(state: RawGestureDetectorState(175370983; gestures: tap; behavior: opaque))
I/flutter ( 6559):                                                        └_GestureSemantics(renderObject: RenderSemanticsGestureHandler relayoutBoundary=up2)
I/flutter ( 6559):                                                         └Listener(listeners: down; behavior: opaque; renderObject: RenderPointerListener relayoutBoundary=up3)
I/flutter ( 6559):                                                          └Container(padding: EdgeInsets(16.0, 0.0, 16.0, 0.0))
I/flutter ( 6559):                                                           └Padding(renderObject: RenderPadding relayoutBoundary=up4)
I/flutter ( 6559):                                                            └Center(alignment: Alignment.center; widthFactor: 1.0; renderObject: RenderPositionedBox relayoutBoundary=up5)
I/flutter ( 6559):                                                             └Text("Dump App")
I/flutter ( 6559):                                                              └RichText(renderObject: RenderParagraph relayoutBoundary=up6)

これは「平坦化された」ツリーで、投影されたすべてのウィジェットが表示されています。 さまざまなビルド機能を通じて。 (これは、次の場合に得られる木です。 あなたが呼ぶtoStringDeep()ウィジェット ツリーのルートにあります)。 ウィジェットには表示されないウィジェットがたくさん表示されます。 アプリケーションのソース。フレームワークによって挿入されるため、 ウィジェットのビルド関数。例えば、InkFeatureの実装の詳細です。Materialウィジェット。

以来、debugDumpApp()ボタンが変化すると呼び出しが呼び出されます 押されてから解放されるまでの時間は一致します。TextButtonオブジェクト呼び出しsetState()したがって、それ自体が汚れているとマークされます。だからこそ、ダンプを見ると、 「ダーティ」としてマークされた特定のオブジェクトが表示されるはずです。なんてこともわかります ジェスチャ リスナーが登録されています。この場合、単一の GestureDetector がリストされており、「タップ」ジェスチャのみをリッスンしています (「タップ」は、TapGestureDetectortoStringShort関数)。

独自のウィジェットを作成する場合は、オーバーライドすることで情報を追加できます。debugFillProperties()。追加診断プロパティオブジェクトをメソッドの引数に追加し、スーパークラスのメソッドを呼び出します。 この機能とは、toStringを埋めるために使用するメソッド ウィジェットの説明。

レンダーツリー

レイアウトの問題をデバッグしようとしている場合は、ウィジェット レイヤーの ツリーの詳細が不十分である可能性があります。その場合、ダンプできます 呼び出しによるツリーのレンダリングdebugDumpRenderTree()。 同様にdebugDumpApp()、これは多かれ少なかれいつでも呼び出すことができます ただし、レイアウトまたはペイント段階中は除きます。原則として、 からそれを呼び出すフレームコールバックまたは、イベント ハンドラーが最適な解決策です。

電話をかけるにはdebugDumpRenderTree()を追加する必要がありますimport 'package:flutter/rendering.dart';ソースファイルに。

前の小さな例の出力は次のようになります。 以下:

I/flutter ( 6559): RenderView
I/flutter ( 6559):  │ debug mode enabled - android
I/flutter ( 6559):  │ window size: Size(1080.0, 1794.0) (in physical pixels)
I/flutter ( 6559):  │ device pixel ratio: 2.625 (physical pixels per logical pixel)
I/flutter ( 6559):  │ configuration: Size(411.4, 683.4) at 2.625x (in logical pixels)
I/flutter ( 6559):  │
I/flutter ( 6559):  └─child: RenderCustomPaint
I/flutter ( 6559):    │ creator: CustomPaint ← Banner ← CheckedModeBanner ←
I/flutter ( 6559):    │   WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)] ←
I/flutter ( 6559):    │   Theme ← AnimatedTheme ← ScrollConfiguration ← MaterialApp ←
I/flutter ( 6559):    │   [root]
I/flutter ( 6559):    │ parentData: <none>
I/flutter ( 6559):    │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):    │ size: Size(411.4, 683.4)
I/flutter ( 6559):    │
I/flutter ( 6559):    └─child: RenderPointerListener
I/flutter ( 6559):      │ creator: Listener ← Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559):      │   _WidgetsAppState(552902158)] ← Title ← LocaleQuery ← MediaQuery
I/flutter ( 6559):      │   ← DefaultTextStyle ← CustomPaint ← Banner ← CheckedModeBanner ←
I/flutter ( 6559):      │   WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)] ←
I/flutter ( 6559):      │   Theme ← AnimatedTheme ← ⋯
I/flutter ( 6559):      │ parentData: <none>
I/flutter ( 6559):      │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):      │ size: Size(411.4, 683.4)
I/flutter ( 6559):      │ behavior: defer-to-child
I/flutter ( 6559):      │ listeners: down, up, cancel
I/flutter ( 6559):      │
I/flutter ( 6559):      └─child: RenderAbsorbPointer
I/flutter ( 6559):        │ creator: AbsorbPointer ← Listener ←
I/flutter ( 6559):        │   Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559):        │   _WidgetsAppState(552902158)] ← Title ← LocaleQuery ← MediaQuery
I/flutter ( 6559):        │   ← DefaultTextStyle ← CustomPaint ← Banner ← CheckedModeBanner ←
I/flutter ( 6559):        │   WidgetsApp-[GlobalObjectKey _MaterialAppState(1009803148)] ←
I/flutter ( 6559):        │   Theme ← ⋯
I/flutter ( 6559):        │ parentData: <none>
I/flutter ( 6559):        │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):        │ size: Size(411.4, 683.4)
I/flutter ( 6559):        │ absorbing: false
I/flutter ( 6559):        │
I/flutter ( 6559):        └─child: RenderSemanticsAnnotations
I/flutter ( 6559):          │ creator: Semantics ← Focus-[GlobalKey 489139594] ← AbsorbPointer
I/flutter ( 6559):          │   ← Listener ← Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559):          │   _WidgetsAppState(552902158)] ← Title ← LocaleQuery ← MediaQuery
I/flutter ( 6559):          │   ← DefaultTextStyle ← CustomPaint ← Banner ← CheckedModeBanner ←
I/flutter ( 6559):          │   ⋯
I/flutter ( 6559):          │ parentData: <none>
I/flutter ( 6559):          │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):          │ size: Size(411.4, 683.4)
I/flutter ( 6559):          │
I/flutter ( 6559):          └─child: _RenderTheatre
I/flutter ( 6559):            │ creator: _Theatre ← Overlay-[GlobalKey 199833992] ← _FocusScope ←
I/flutter ( 6559):            │   Semantics ← Focus-[GlobalKey 489139594] ← AbsorbPointer ←
I/flutter ( 6559):            │   Listener ← Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559):            │   _WidgetsAppState(552902158)] ← Title ← LocaleQuery ← MediaQuery
I/flutter ( 6559):            │   ← DefaultTextStyle ← ⋯
I/flutter ( 6559):            │ parentData: <none>
I/flutter ( 6559):            │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            │ size: Size(411.4, 683.4)
I/flutter ( 6559):            │
I/flutter ( 6559):            ├─onstage: RenderStack
I/flutter ( 6559):            ╎ │ creator: Stack ← _Theatre ← Overlay-[GlobalKey 199833992] ←
I/flutter ( 6559):            ╎ │   _FocusScope ← Semantics ← Focus-[GlobalKey 489139594] ←
I/flutter ( 6559):            ╎ │   AbsorbPointer ← Listener ←
I/flutter ( 6559):            ╎ │   Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559):            ╎ │   _WidgetsAppState(552902158)] ← Title ← LocaleQuery ← MediaQuery
I/flutter ( 6559):            ╎ │   ← ⋯
I/flutter ( 6559):            ╎ │ parentData: not positioned; offset=Offset(0.0, 0.0)
I/flutter ( 6559):            ╎ │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎ │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎ │
I/flutter ( 6559):            ╎ ├─child 1: RenderIgnorePointer
I/flutter ( 6559):            ╎ │ │ creator: IgnorePointer ← _OverlayEntry-[GlobalKey 612888877] ←
I/flutter ( 6559):            ╎ │ │   Stack ← _Theatre ← Overlay-[GlobalKey 199833992] ← _FocusScope
I/flutter ( 6559):            ╎ │ │   ← Semantics ← Focus-[GlobalKey 489139594] ← AbsorbPointer ←
I/flutter ( 6559):            ╎ │ │   Listener ← Navigator-[GlobalObjectKey<NavigatorState>
I/flutter ( 6559):            ╎ │ │   _WidgetsAppState(552902158)] ← Title ← ⋯
I/flutter ( 6559):            ╎ │ │ parentData: not positioned; offset=Offset(0.0, 0.0)
I/flutter ( 6559):            ╎ │ │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎ │ │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎ │ │ ignoring: false
I/flutter ( 6559):            ╎ │ │ ignoringSemantics: implicitly false
I/flutter ( 6559):            ╎ │ │
I/flutter ( 6559):            ╎ │ └─child: RenderSemanticsAnnotations
I/flutter ( 6559):            ╎ │   │ creator: Semantics ← ModalBarrier ← IgnorePointer ←
I/flutter ( 6559):            ╎ │   │   _OverlayEntry-[GlobalKey 612888877] ← Stack ← _Theatre ←
I/flutter ( 6559):            ╎ │   │   Overlay-[GlobalKey 199833992] ← _FocusScope ← Semantics ←
I/flutter ( 6559):            ╎ │   │   Focus-[GlobalKey 489139594] ← AbsorbPointer ← Listener ← ⋯
I/flutter ( 6559):            ╎ │   │ parentData: <none>
I/flutter ( 6559):            ╎ │   │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎ │   │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎ │   │
I/flutter ( 6559):            ╎ │   └─child: RenderSemanticsGestureHandler
I/flutter ( 6559):            ╎ │     │ creator: _GestureSemantics ← RawGestureDetector ← GestureDetector
I/flutter ( 6559):            ╎ │     │   ← Semantics ← ModalBarrier ← IgnorePointer ←
I/flutter ( 6559):            ╎ │     │   _OverlayEntry-[GlobalKey 612888877] ← Stack ← _Theatre ←
I/flutter ( 6559):            ╎ │     │   Overlay-[GlobalKey 199833992] ← _FocusScope ← Semantics ← ⋯
I/flutter ( 6559):            ╎ │     │ parentData: <none>
I/flutter ( 6559):            ╎ │     │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎ │     │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎ │     │
I/flutter ( 6559):            ╎ │     └─child: RenderPointerListener
I/flutter ( 6559):            ╎ │       │ creator: Listener ← _GestureSemantics ← RawGestureDetector ←
I/flutter ( 6559):            ╎ │       │   GestureDetector ← Semantics ← ModalBarrier ← IgnorePointer ←
I/flutter ( 6559):            ╎ │       │   _OverlayEntry-[GlobalKey 612888877] ← Stack ← _Theatre ←
I/flutter ( 6559):            ╎ │       │   Overlay-[GlobalKey 199833992] ← _FocusScope ← ⋯
I/flutter ( 6559):            ╎ │       │ parentData: <none>
I/flutter ( 6559):            ╎ │       │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎ │       │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎ │       │ behavior: opaque
I/flutter ( 6559):            ╎ │       │ listeners: down
I/flutter ( 6559):            ╎ │       │
I/flutter ( 6559):            ╎ │       └─child: RenderConstrainedBox
I/flutter ( 6559):            ╎ │           creator: ConstrainedBox ← Listener ← _GestureSemantics ←
I/flutter ( 6559):            ╎ │             RawGestureDetector ← GestureDetector ← Semantics ← ModalBarrier
I/flutter ( 6559):            ╎ │             ← IgnorePointer ← _OverlayEntry-[GlobalKey 612888877] ← Stack ←
I/flutter ( 6559):            ╎ │             _Theatre ← Overlay-[GlobalKey 199833992] ← ⋯
I/flutter ( 6559):            ╎ │           parentData: <none>
I/flutter ( 6559):            ╎ │           constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎ │           size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎ │           additionalConstraints: BoxConstraints(biggest)
I/flutter ( 6559):            ╎ │
I/flutter ( 6559):            ╎ └─child 2: RenderSemanticsAnnotations
I/flutter ( 6559):            ╎   │ creator: Semantics ← Focus-[GlobalObjectKey
I/flutter ( 6559):            ╎   │   MaterialPageRoute<void>(875520219)] ← _ModalScope-[GlobalKey
I/flutter ( 6559):            ╎   │   816151164] ← _OverlayEntry-[GlobalKey 727622716] ← Stack ←
I/flutter ( 6559):            ╎   │   _Theatre ← Overlay-[GlobalKey 199833992] ← _FocusScope ←
I/flutter ( 6559):            ╎   │   Semantics ← Focus-[GlobalKey 489139594] ← AbsorbPointer ←
I/flutter ( 6559):            ╎   │   Listener ← ⋯
I/flutter ( 6559):            ╎   │ parentData: not positioned; offset=Offset(0.0, 0.0)
I/flutter ( 6559):            ╎   │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎   │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎   │
I/flutter ( 6559):            ╎   └─child: RenderOffstage
I/flutter ( 6559):            ╎     │ creator: Offstage ← _FocusScope ← Semantics ←
I/flutter ( 6559):            ╎     │   Focus-[GlobalObjectKey MaterialPageRoute<void>(875520219)] ←
I/flutter ( 6559):            ╎     │   _ModalScope-[GlobalKey 816151164] ← _OverlayEntry-[GlobalKey
I/flutter ( 6559):            ╎     │   727622716] ← Stack ← _Theatre ← Overlay-[GlobalKey 199833992] ←
I/flutter ( 6559):            ╎     │   _FocusScope ← Semantics ← Focus-[GlobalKey 489139594] ← ⋯
I/flutter ( 6559):            ╎     │ parentData: <none>
I/flutter ( 6559):            ╎     │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎     │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎     │ offstage: false
I/flutter ( 6559):            ╎     │
I/flutter ( 6559):            ╎     └─child: RenderIgnorePointer
I/flutter ( 6559):            ╎       │ creator: IgnorePointer ← Offstage ← _FocusScope ← Semantics ←
I/flutter ( 6559):            ╎       │   Focus-[GlobalObjectKey MaterialPageRoute<void>(875520219)] ←
I/flutter ( 6559):            ╎       │   _ModalScope-[GlobalKey 816151164] ← _OverlayEntry-[GlobalKey
I/flutter ( 6559):            ╎       │   727622716] ← Stack ← _Theatre ← Overlay-[GlobalKey 199833992] ←
I/flutter ( 6559):            ╎       │   _FocusScope ← Semantics ← ⋯
I/flutter ( 6559):            ╎       │ parentData: <none>
I/flutter ( 6559):            ╎       │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎       │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎       │ ignoring: false
I/flutter ( 6559):            ╎       │ ignoringSemantics: implicitly false
I/flutter ( 6559):            ╎       │
I/flutter ( 6559):            ╎       └─child: RenderFractionalTranslation
I/flutter ( 6559):            ╎         │ creator: FractionalTranslation ← SlideTransition ←
I/flutter ( 6559):            ╎         │   _MountainViewPageTransition ← IgnorePointer ← Offstage ←
I/flutter ( 6559):            ╎         │   _FocusScope ← Semantics ← Focus-[GlobalObjectKey
I/flutter ( 6559):            ╎         │   MaterialPageRoute<void>(875520219)] ← _ModalScope-[GlobalKey
I/flutter ( 6559):            ╎         │   816151164] ← _OverlayEntry-[GlobalKey 727622716] ← Stack ←
I/flutter ( 6559):            ╎         │   _Theatre ← ⋯
I/flutter ( 6559):            ╎         │ parentData: <none>
I/flutter ( 6559):            ╎         │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎         │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎         │ translation: Offset(0.0, 0.0)
I/flutter ( 6559):            ╎         │ transformHitTests: true
I/flutter ( 6559):            ╎         │
I/flutter ( 6559):            ╎         └─child: RenderRepaintBoundary
I/flutter ( 6559):            ╎           │ creator: RepaintBoundary ← FractionalTranslation ←
I/flutter ( 6559):            ╎           │   SlideTransition ← _MountainViewPageTransition ← IgnorePointer ←
I/flutter ( 6559):            ╎           │   Offstage ← _FocusScope ← Semantics ← Focus-[GlobalObjectKey
I/flutter ( 6559):            ╎           │   MaterialPageRoute<void>(875520219)] ← _ModalScope-[GlobalKey
I/flutter ( 6559):            ╎           │   816151164] ← _OverlayEntry-[GlobalKey 727622716] ← Stack ← ⋯
I/flutter ( 6559):            ╎           │ parentData: <none>
I/flutter ( 6559):            ╎           │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎           │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎           │ metrics: 83.3% useful (1 bad vs 5 good)
I/flutter ( 6559):            ╎           │ diagnosis: this is a useful repaint boundary and should be kept
I/flutter ( 6559):            ╎           │
I/flutter ( 6559):            ╎           └─child: RenderDecoratedBox
I/flutter ( 6559):            ╎             │ creator: DecoratedBox ← Container ← AnimatedContainer ← Material
I/flutter ( 6559):            ╎             │   ← AppHome ← _ModalScopeStatus ← PageStorage-[GlobalKey
I/flutter ( 6559):            ╎             │   619728754] ← RepaintBoundary ← FractionalTranslation ←
I/flutter ( 6559):            ╎             │   SlideTransition ← _MountainViewPageTransition ← IgnorePointer ←
I/flutter ( 6559):            ╎             │   ⋯
I/flutter ( 6559):            ╎             │ parentData: <none>
I/flutter ( 6559):            ╎             │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎             │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎             │ decoration:
I/flutter ( 6559):            ╎             │   <no decorations specified>
I/flutter ( 6559):            ╎             │ configuration: ImageConfiguration(bundle:
I/flutter ( 6559):            ╎             │   PlatformAssetBundle@367106502(), devicePixelRatio: 2.625,
I/flutter ( 6559):            ╎             │   platform: android)
I/flutter ( 6559):            ╎             │
I/flutter ( 6559):            ╎             └─child: RenderDecoratedBox
I/flutter ( 6559):            ╎               │ creator: DecoratedBox ← Container ← DecoratedBox ← Container ←
I/flutter ( 6559):            ╎               │   AnimatedContainer ← Material ← AppHome ← _ModalScopeStatus ←
I/flutter ( 6559):            ╎               │   PageStorage-[GlobalKey 619728754] ← RepaintBoundary ←
I/flutter ( 6559):            ╎               │   FractionalTranslation ← SlideTransition ← ⋯
I/flutter ( 6559):            ╎               │ parentData: <none>
I/flutter ( 6559):            ╎               │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎               │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎               │ decoration:
I/flutter ( 6559):            ╎               │   backgroundColor: Color(0xfffafafa)
I/flutter ( 6559):            ╎               │ configuration: ImageConfiguration(bundle:
I/flutter ( 6559):            ╎               │   PlatformAssetBundle@367106502(), devicePixelRatio: 2.625,
I/flutter ( 6559):            ╎               │   platform: android)
I/flutter ( 6559):            ╎               │
I/flutter ( 6559):            ╎               └─child: _RenderInkFeatures
I/flutter ( 6559):            ╎                 │ creator: _InkFeature-[GlobalKey ink renderer] ←
I/flutter ( 6559):            ╎                 │   NotificationListener<LayoutChangedNotification> ← DecoratedBox
I/flutter ( 6559):            ╎                 │   ← Container ← DecoratedBox ← Container ← AnimatedContainer ←
I/flutter ( 6559):            ╎                 │   Material ← AppHome ← _ModalScopeStatus ← PageStorage-[GlobalKey
I/flutter ( 6559):            ╎                 │   619728754] ← RepaintBoundary ← ⋯
I/flutter ( 6559):            ╎                 │ parentData: <none>
I/flutter ( 6559):            ╎                 │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎                 │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎                 │
I/flutter ( 6559):            ╎                 └─child: RenderPositionedBox
I/flutter ( 6559):            ╎                   │ creator: Center ← DefaultTextStyle ← AnimatedDefaultTextStyle ←
I/flutter ( 6559):            ╎                   │   _InkFeature-[GlobalKey ink renderer] ←
I/flutter ( 6559):            ╎                   │   NotificationListener<LayoutChangedNotification> ← DecoratedBox
I/flutter ( 6559):            ╎                   │   ← Container ← DecoratedBox ← Container ← AnimatedContainer ←
I/flutter ( 6559):            ╎                   │   Material ← AppHome ← ⋯
I/flutter ( 6559):            ╎                   │ parentData: <none>
I/flutter ( 6559):            ╎                   │ constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter ( 6559):            ╎                   │ size: Size(411.4, 683.4)
I/flutter ( 6559):            ╎                   │ alignment: Alignment.center
I/flutter ( 6559):            ╎                   │ widthFactor: expand
I/flutter ( 6559):            ╎                   │ heightFactor: expand
I/flutter ( 6559):            ╎                   │
I/flutter ( 6559):            ╎                   └─child: RenderConstrainedBox relayoutBoundary=up1
I/flutter ( 6559):            ╎                     │ creator: ConstrainedBox ← MaterialButton ← TextButton ← Center ←
I/flutter ( 6559):            ╎                     │   DefaultTextStyle ← AnimatedDefaultTextStyle ←
I/flutter ( 6559):            ╎                     │   _InkFeature-[GlobalKey ink renderer] ←
I/flutter ( 6559):            ╎                     │   NotificationListener<LayoutChangedNotification> ← DecoratedBox
I/flutter ( 6559):            ╎                     │   ← Container ← DecoratedBox ← Container ← ⋯
I/flutter ( 6559):            ╎                     │ parentData: offset=Offset(156.7, 323.7)
I/flutter ( 6559):            ╎                     │ constraints: BoxConstraints(0.0<=w<=411.4, 0.0<=h<=683.4)
I/flutter ( 6559):            ╎                     │ size: Size(98.0, 36.0)
I/flutter ( 6559):            ╎                     │ additionalConstraints: BoxConstraints(88.0<=w<=Infinity, h=36.0)
I/flutter ( 6559):            ╎                     │
I/flutter ( 6559):            ╎                     └─child: RenderSemanticsGestureHandler relayoutBoundary=up2
I/flutter ( 6559):            ╎                       │ creator: _GestureSemantics ← RawGestureDetector ← GestureDetector
I/flutter ( 6559):            ╎                       │   ← InkWell ← IconTheme ← DefaultTextStyle ←
I/flutter ( 6559):            ╎                       │   AnimatedDefaultTextStyle ← ConstrainedBox ← MaterialButton ←
I/flutter ( 6559):            ╎                       │   TextButton ← Center ← DefaultTextStyle ← ⋯
I/flutter ( 6559):            ╎                       │ parentData: <none>
I/flutter ( 6559):            ╎                       │ constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
I/flutter ( 6559):            ╎                       │ size: Size(98.0, 36.0)
I/flutter ( 6559):            ╎                       │
I/flutter ( 6559):            ╎                       └─child: RenderPointerListener relayoutBoundary=up3
I/flutter ( 6559):            ╎                         │ creator: Listener ← _GestureSemantics ← RawGestureDetector ←
I/flutter ( 6559):            ╎                         │   GestureDetector ← InkWell ← IconTheme ← DefaultTextStyle ←
I/flutter ( 6559):            ╎                         │   AnimatedDefaultTextStyle ← ConstrainedBox ← MaterialButton ←
I/flutter ( 6559):            ╎                         │   TextButton ← Center ← ⋯
I/flutter ( 6559):            ╎                         │ parentData: <none>
I/flutter ( 6559):            ╎                         │ constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
I/flutter ( 6559):            ╎                         │ size: Size(98.0, 36.0)
I/flutter ( 6559):            ╎                         │ behavior: opaque
I/flutter ( 6559):            ╎                         │ listeners: down
I/flutter ( 6559):            ╎                         │
I/flutter ( 6559):            ╎                         └─child: RenderPadding relayoutBoundary=up4
I/flutter ( 6559):            ╎                           │ creator: Padding ← Container ← Listener ← _GestureSemantics ←
I/flutter ( 6559):            ╎                           │   RawGestureDetector ← GestureDetector ← InkWell ← IconTheme ←
I/flutter ( 6559):            ╎                           │   DefaultTextStyle ← AnimatedDefaultTextStyle ← ConstrainedBox ←
I/flutter ( 6559):            ╎                           │   MaterialButton ← ⋯
I/flutter ( 6559):            ╎                           │ parentData: <none>
I/flutter ( 6559):            ╎                           │ constraints: BoxConstraints(88.0<=w<=411.4, h=36.0)
I/flutter ( 6559):            ╎                           │ size: Size(98.0, 36.0)
I/flutter ( 6559):            ╎                           │ padding: EdgeInsets(16.0, 0.0, 16.0, 0.0)
I/flutter ( 6559):            ╎                           │
I/flutter ( 6559):            ╎                           └─child: RenderPositionedBox relayoutBoundary=up5
I/flutter ( 6559):            ╎                             │ creator: Center ← Padding ← Container ← Listener ←
I/flutter ( 6559):            ╎                             │   _GestureSemantics ← RawGestureDetector ← GestureDetector ←
I/flutter ( 6559):            ╎                             │   InkWell ← IconTheme ← DefaultTextStyle ←
I/flutter ( 6559):            ╎                             │   AnimatedDefaultTextStyle ← ConstrainedBox ← ⋯
I/flutter ( 6559):            ╎                             │ parentData: offset=Offset(16.0, 0.0)
I/flutter ( 6559):            ╎                             │ constraints: BoxConstraints(56.0<=w<=379.4, h=36.0)
I/flutter ( 6559):            ╎                             │ size: Size(66.0, 36.0)
I/flutter ( 6559):            ╎                             │ alignment: Alignment.center
I/flutter ( 6559):            ╎                             │ widthFactor: 1.0
I/flutter ( 6559):            ╎                             │ heightFactor: expand
I/flutter ( 6559):            ╎                             │
I/flutter ( 6559):            ╎                             └─child: RenderParagraph relayoutBoundary=up6
I/flutter ( 6559):            ╎                               │ creator: RichText ← Text ← Center ← Padding ← Container ←
I/flutter ( 6559):            ╎                               │   Listener ← _GestureSemantics ← RawGestureDetector ←
I/flutter ( 6559):            ╎                               │   GestureDetector ← InkWell ← IconTheme ← DefaultTextStyle ← ⋯
I/flutter ( 6559):            ╎                               │ parentData: offset=Offset(0.0, 10.0)
I/flutter ( 6559):            ╎                               │ constraints: BoxConstraints(0.0<=w<=379.4, 0.0<=h<=36.0)
I/flutter ( 6559):            ╎                               │ size: Size(66.0, 16.0)
I/flutter ( 6559):            ╎                               ╘═╦══ text ═══
I/flutter ( 6559):            ╎                                 ║ TextSpan:
I/flutter ( 6559):            ╎                                 ║   inherit: false
I/flutter ( 6559):            ╎                                 ║   color: Color(0xdd000000)
I/flutter ( 6559):            ╎                                 ║   family: "Roboto"
I/flutter ( 6559):            ╎                                 ║   size: 14.0
I/flutter ( 6559):            ╎                                 ║   weight: 500
I/flutter ( 6559):            ╎                                 ║   baseline: alphabetic
I/flutter ( 6559):            ╎                                 ║   "Dump App"
I/flutter ( 6559):            ╎                                 ╚═══════════
I/flutter ( 6559):            ╎
I/flutter ( 6559):            └╌no offstage children

これはルートの出力ですRenderObjectオブジェクトのtoStringDeep()関数。

レイアウトの問題をデバッグする場合、注目すべき重要なフィールドは次のとおりです。sizeconstraints田畑。制約はツリーの下に流れていきます。 そしてサイズは元に戻ります。

たとえば、前のダンプでは、ウィンドウ サイズがSize(411.4, 683.4)、すべてのボックスを強制的に下に置くために使用されます。RenderPositionedBox画面のサイズになります。 の制約BoxConstraints(w=411.4, h=683.4)。 のRenderPositionedBox、ダンプには、によって作成されたことが示されています。Centerウィジェット (で説明されているように)creator分野)、 子の制約をこれの緩いバージョンに設定します。BoxConstraints(0.0<=w<=411.4, 0.0<=h<=683.4)。その子、RenderPadding、さらにこれらの制約を挿入して、 パディングのためのスペースがあるため、RenderConstrainedBoxという緩い制約があるBoxConstraints(0.0<=w<=395.4, 0.0<=h<=667.4)。このオブジェクトは、creatorフィールドが教えてくれたのは、 おそらくその一部TextButtonの定義、 コンテンツの最小幅を 88 ピクセルに設定し、 比高36.0。 (これはTextButtonクラス実装 ボタンの寸法に関するマテリアル デザイン ガイドライン。)

一番奥のRenderPositionedBox再び制約を緩めると、 今度はテキストをボタン内の中央に配置します。のRenderParagraph内容に基づいてサイズが選択されます。 ここで、チェーンを遡ってサイズを追跡すると、 テキストのサイズがどのように影響するかがわかります。 ボタンを形成するすべてのボックスの幅。 お子様の寸法を自分自身のサイズに合わせて調整します。

これを確認するもう 1 つの方法は、「relayoutSubtreeRoot」を確認することです。 各ボックスの説明の一部。基本的にその方法を示しています。 多くの先祖は、何らかの形でこの要素のサイズに依存しています。 したがって、RenderParagraphがありますrelayoutSubtreeRoot=up8、 つまり、RenderParagraph汚れている、 8人の祖先も汚れていなければなりません。 新しい次元の影響を受けます。

独自のレンダー オブジェクトを作成する場合は、 オーバーライドによるダンプdebugFillProperties()。 追加診断プロパティオブジェクトをメソッドの引数に追加し、スーパークラスのメソッドを呼び出します。

レイヤーツリー

合成の問題をデバッグしようとしている場合は、次を使用できます。debugDumpLayerTree()。 前の例の場合、次のように出力されます。

I/flutter : TransformLayer
I/flutter :  │ creator: [root]
I/flutter :  │ offset: Offset(0.0, 0.0)
I/flutter :  │ transform:
I/flutter :  │   [0] 3.5,0.0,0.0,0.0
I/flutter :  │   [1] 0.0,3.5,0.0,0.0
I/flutter :  │   [2] 0.0,0.0,1.0,0.0
I/flutter :  │   [3] 0.0,0.0,0.0,1.0
I/flutter :  │
I/flutter :  ├─child 1: OffsetLayer
I/flutter :  │ │ creator: RepaintBoundary ← _FocusScope ← Semantics ← Focus-[GlobalObjectKey MaterialPageRoute(560156430)] ← _ModalScope-[GlobalKey 328026813] ← _OverlayEntry-[GlobalKey 388965355] ← Stack ← Overlay-[GlobalKey 625702218] ← Navigator-[GlobalObjectKey _MaterialAppState(859106034)] ← Title ← ⋯
I/flutter :  │ │ offset: Offset(0.0, 0.0)
I/flutter :  │ │
I/flutter :  │ └─child 1: PictureLayer
I/flutter :  │
I/flutter :  └─child 2: PictureLayer

これは呼び出しの出力ですtoStringDeep根元にLayer物体。

ルートの変換はデバイスを適用する変換です ピクセル比。この場合、各デバイス ピクセルの比率は 3.5 になります。 論理ピクセル。

RepaintBoundaryウィジェット、RenderRepaintBoundaryレンダー ツリーで、レイヤー ツリーに新しいレイヤーを作成します。これは 再塗装の必要量を減らすために使用されます。

フォーカスツリー

フォーカスまたはショートカットの問題をデバッグするには、フォーカス ツリーをダンプします。 使用してdebugDumpFocusTree()

例えば:

I/flutter : FocusManager#6fb59
I/flutter :  │ primaryFocus: FocusScopeNode#3c26f(_ModalScopeState<dynamic>
I/flutter :  │   Focus Scope [PRIMARY FOCUS])
I/flutter :  │ primaryFocusCreator: FocusScope ← PrimaryScrollController ←
I/flutter :  │   _ActionsScope ← Actions ← Builder ← PageStorage ← Offstage ←
I/flutter :  │   _ModalScopeStatus ← UnmanagedRestorationScope ←
I/flutter :  │   RestorationScope ← AnimatedBuilder ←
I/flutter :  │   _ModalScope<dynamic>-[LabeledGlobalKey<_ModalScopeState<dynamic>>#f36a2]
I/flutter :  │   ← Semantics ← _RenderTheaterMarker ← _EffectiveTickerMode ←
I/flutter :  │   TickerMode ←
I/flutter :  │   _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#2e2a3]
I/flutter :  │   ← _Theater ← Overlay-[LabeledGlobalKey<OverlayState>#89fc1] ←
I/flutter :  │   UnmanagedRestorationScope ← ⋯
I/flutter :  │
I/flutter :  └─rootScope: FocusScopeNode#95ff1(Root Focus Scope [IN FOCUS PATH])
I/flutter :    │ IN FOCUS PATH
I/flutter :    │ focusedChildren: FocusScopeNode#001cc(Navigator Scope [IN FOCUS
I/flutter :    │   PATH])
I/flutter :    │
I/flutter :    └─Child 1: FocusNode#79786([IN FOCUS PATH])
I/flutter :      │ context: Focus
I/flutter :      │ NOT FOCUSABLE
I/flutter :      │ IN FOCUS PATH
I/flutter :      │
I/flutter :      └─Child 1: FocusNode#15aec(Shortcuts [IN FOCUS PATH])
I/flutter :        │ context: Focus
I/flutter :        │ NOT FOCUSABLE
I/flutter :        │ IN FOCUS PATH
I/flutter :        │
I/flutter :        └─Child 1: FocusNode#3514b(Shortcuts [IN FOCUS PATH])
I/flutter :          │ context: Focus
I/flutter :          │ NOT FOCUSABLE
I/flutter :          │ IN FOCUS PATH
I/flutter :          │
I/flutter :          └─Child 1: _FocusTraversalGroupNode#0ccda(FocusTraversalGroup [IN FOCUS PATH])
I/flutter :            │ context: Focus
I/flutter :            │ NOT FOCUSABLE
I/flutter :            │ IN FOCUS PATH
I/flutter :            │
I/flutter :            └─Child 1: FocusNode#e2413(Shortcuts [IN FOCUS PATH])
I/flutter :              │ context: Focus
I/flutter :              │ NOT FOCUSABLE
I/flutter :              │ IN FOCUS PATH
I/flutter :              │
I/flutter :              └─Child 1: FocusScopeNode#001cc(Navigator Scope [IN FOCUS PATH])
I/flutter :                │ context: FocusScope
I/flutter :                │ IN FOCUS PATH
I/flutter :                │ focusedChildren: FocusScopeNode#3c26f(_ModalScopeState<dynamic>
I/flutter :                │   Focus Scope [PRIMARY FOCUS])
I/flutter :                │
I/flutter :                └─Child 1: _FocusTraversalGroupNode#1d456(FocusTraversalGroup [IN FOCUS PATH])
I/flutter :                  │ context: Focus
I/flutter :                  │ NOT FOCUSABLE
I/flutter :                  │ IN FOCUS PATH
I/flutter :                  │
I/flutter :                  └─Child 1: FocusNode#3635f(Navigator [IN FOCUS PATH])
I/flutter :                    │ context: Focus
I/flutter :                    │ IN FOCUS PATH
I/flutter :                    │
I/flutter :                    └─Child 1: FocusScopeNode#3c26f(_ModalScopeState<dynamic> Focus Scope [PRIMARY FOCUS])
I/flutter :                        context: FocusScope
I/flutter :                        PRIMARY FOCUS

フォーカスされたノードにはラベルが付けられますPRIMARY FOCUS。フォーカス ノードの祖先は次のとおりです。 ラベルが貼られたIN FOCUS PATH

アプリがFocusウィジェットを使用できます。debugLabelプロパティを使用して、ツリー内でフォーカス ノードを見つけやすくします。

を使用することもできます。debugFocusChanges有効にするブール値のフラグ フォーカスが変更されたときの広範なログ記録。

セマンティクスツリー

セマンティクス ツリーのダンプを取得することもできます。 (システム アクセシビリティ API に提示されるツリー) を使用してdebugDumpSemanticsTree()。これを使用するには、 たとえば、最初にアクセシビリティを有効にする必要があります。 システム アクセシビリティ ツールを有効にするか、SemanticsDebugger

前の例の場合、次のように出力されます。

I/flutter : SemanticsNode(0; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter :  ├SemanticsNode(1; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter :  │ └SemanticsNode(2; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4); canBeTapped)
I/flutter :  └SemanticsNode(3; Rect.fromLTRB(0.0, 0.0, 411.4, 683.4))
I/flutter :    └SemanticsNode(4; Rect.fromLTRB(0.0, 0.0, 82.0, 36.0); canBeTapped; "Dump App")
このツリーは問題があります。https://github.com/flutter/flutter/issues/2476 を参照してください。

スケジュール設定

フレームに対してイベントが発生する場所を確認するには 開始/終了を切り替えることができます。debugPrintBeginFrameBannerそしてそのdebugPrintEndFrameBannerを出力するブール値 フレームの最初と最後をコンソールに送信します。

例えば:

I/flutter : ▄▄▄▄▄▄▄▄ Frame 12         30s 437.086ms ▄▄▄▄▄▄▄▄
I/flutter : Debug print: Am I performing this work more than once per frame?
I/flutter : Debug print: Am I performing this work more than once per frame?
I/flutter : ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

debugPrintScheduleFrameStacksフラグも使用できます 現在のフレームをスケジュールする呼び出しスタックを出力します。

デバッグフラグ: レイアウト

設定することで、レイアウトの問題を視覚的にデバッグすることもできます。debugPaintSizeEnabledtrue。 これはからのブール値ですrendering図書館。かもね いつでも有効になり、true の間はすべてのペイントに影響します。 設定する最も簡単な方法は、void main()エントリーポイント。次のコードの例を参照してください。

//add import to rendering library
import 'package:flutter/rendering.dart';

void main() {
  debugPaintSizeEnabled = true;
  runApp(const MyApp());
}

有効にすると、すべてのボックスに明るい青緑の境界線が表示されます。 パディング(次のようなウィジェットから)Padding) は色褪せて表示されます 青、子の周りに濃い青のボックス、位置合わせ (次のようなウィジェットからCenterAlign) で表示されます 黄色の矢印とスペーサー (次のようなウィジェットから)Container子供がいない場合)は灰色で表示されます。

debugPaintBaselinesEnabled国旗 同様のことを行いますが、ベースラインを持つオブジェクトに対して行われます。 アルファベットのベースラインは明るい緑色で表示され、 オレンジ色の表意文字ベースライン。

debugPaintPointersEnabledフラグがオンになる タップされているオブジェクトをすべて削除する特別なモード ティール色で強調表示されます。これは判断に役立ちます オブジェクトが何らかの理由で正しくヒットしていないかどうか テスト (これは、たとえば、実際にテストされた場合に発生する可能性があります) 親の境界外にあるため、 そもそもヒット テストの対象として検討されています)。

たとえば、コンポジター レイヤーをデバッグしようとしている場合、 追加するかどうか、そしてどこに追加するかを決定するRepaintBoundaryウィジェットを使用できます。debugPaintLayerBordersEnabled各レイヤーの境界をオレンジ色で囲むフラグ、 またはdebugRepaintRainbowEnabled国旗、 これにより、レイヤーが回転するセットでオーバーレイされます。 再塗装されるたびに色が変わります。

これらのフラグはすべて、次の環境でのみ機能します。デバッグモード。 一般に、Flutter フレームワーク内の次のものはすべて、 「debug...」はデバッグモードでのみ動作します。

アニメーションのデバッグ

をセットするtimeDilation変数 (からschedulerlibrary) を 1.0 より大きい数値 (たとえば、50.0) に設定します。 これはアプリの起動時に一度だけ設定することをお勧めします。もし、あんたが 特に、途中で減らす場合は、その場で変更します。 アニメーションが実行されている場合、フレームワークが 時間が逆行することを観察することになるでしょう。 結果としてアサートが発生し、通常は作業が妨げられます。

デバッグフラグ:パフォーマンス

Flutter はさまざまなデバッグ フラグと関数を提供します のさまざまな時点でアプリをデバッグするのに役立ちます。 開発サイクル。これらの機能を使用するには、コンパイルする必要があります デバッグモードで。次のリストは完全ではありませんが、 のいくつかのフラグ (および 1 つの関数) を強調表示します。レンダリングライブラリパフォーマンスの問題をデバッグするため。

これらのフラグは、フレームワーク コードを編集することによって設定できます。 または、モジュールをインポートして値を設定します。main()方法の後にホットリスタートが続きます。

debugDumpRenderTree()

レイアウトまたは再描画中でないときにこの関数を呼び出します。 レンダリング ツリーをコンソールにダンプするフェーズ。 (押すtからflutter runこのコマンドを呼び出します。) 「RepaintBoundary」を検索して診断を表示します 境界線がどれほど役立つかについて。

debugPaintLayerBordersEnabled

保留中

debugRepaintRainbowEnabled

Flutter でこのフラグを有効にすることができます。 インスペクターを選択して、ハイライトの再ペイントボタン。 静的ウィジェットが虹の色で回転している場合 (静的ヘッダーなど)、これらの領域は追加の候補です。 境界線を再描画します。

debugPrintMarkNeedsLayoutStacks

さらに多くのレイアウトを表示する場合は、このフラグを有効にします 予想よりも (たとえば、タイムライン上、プロフィール上、 またはからprintレイアウトメソッド内のステートメント)。 有効にすると、コンソールにスタック トレースが表示されます。 各レンダー オブジェクトがダーティとしてマークされる理由を示す レイアウト。使用できますdebugPrintStack()からのメソッドservices独自のスタック トレースをオンデマンドで出力するライブラリ、 この種のアプローチがあなたにとって役立つのであれば。

debugPrintMarkNeedsPaintStacks

に似ているdebugPrintMarkNeedsLayoutStacks、 ただし余分な塗装のため。使用できますdebugPrintStack()からのメソッドservices独自のスタックを印刷するライブラリ この種のアプローチが役立つ場合は、オンデマンドでトレースします。

Dart コードのパフォーマンスのトレース

カスタム パフォーマンス トレースをプログラムで実行するには、 Dart コードの任意のセグメントの壁/CPU 時間を測定します。 Android で行うことと同様ですシステムレース、 使用dart:developer タイムラインをラップするユーティリティ 次のような測定したいコード:

import 'dart:developer';

void main() {
  Timeline.startSync('interesting function');
  // iWonderHowLongThisTakes();
  Timeline.finishSync();
}

次に、DevTools を開きますタイムラインイベントチャートアプリに接続している間、 を確認してくださいダーツ録音オプションがチェックされているパフォーマンス設定、 測定したい機能を実行します。

必ずアプリを実行してくださいプロファイルモード確実に 実行時のパフォーマンス特性は、使用しているパフォーマンス特性とほぼ一致します。 最終製品。

パフォーマンスオーバーレイ

PerformanceOverlay ウィジェットをプログラムで有効にするには、次のようにします。 を設定するshowPerformanceOverlay財産をtrueMaterialAppCupertinoApp、 またWidgetsAppコンストラクタ:

import 'package:flutter/material.dart';

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      showPerformanceOverlay: true,
      title: 'My Awesome App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'My Awesome App'),
    );
  }
}

(使用していない場合は、MaterialAppCupertinoApp、 またWidgetsAppをラップしても同じ効果が得られます。 アプリケーションをスタックに追加し、ウィジェットをスタックに配置します。 電話して作成したPerformanceOverlay.allEnabled()。)

オーバーレイ内のグラフを解釈する方法については、 見るパフォーマンスオーバーレイFlutter パフォーマンスのプロファイリング

ウィジェット配置グリッド

プログラムでオーバーレイすることができますマテリアル デザイン ベースライン グリッドアプリの上に を使用して位置合わせを確認するのに役立ちます。debugShowMaterialGridの引数MaterialAppコンストラクタ。

マテリアル以外のアプリケーションでも、同様のことを実現できます。 を使用することによる効果GridPaperウィジェットを直接。