フラッター例外のキャッチ

Flutter フレームワークの例外キャッチ

Flutter フレームワークは、多くの主要なメソッドの例外をキャプチャします。
レイアウトが範囲外または仕様外になると、Flutter は自動的にエラー インターフェイスをポップアップ表示します。たとえば、
画像.png
コードにエラーがあっても、APP がクラッシュすることはありません。Flutter は例外をキャッチするのに役立ちます。

Flutter では、Widget は対応する Element を作成し、StatefulWidget は StatefulElement を作成し、StatelessWidget は StatelessElement を作成します。StatefulElement と StatelessElement は両方とも ComponentElement です。

  /// Calls the [StatelessWidget.build] method of the [StatelessWidget] object
  /// (for stateless widgets) or the [State.build] method of the [State] object
  /// (for stateful widgets) and then updates the widget tree.
  ///
  /// Called automatically during [mount] to generate the first build, and by
  /// [rebuild] when the element needs updating.
  @override
  @pragma('vm:notify-debugger-on-exception')
  void performRebuild() {
    Widget? built;
    try {
      ...
      //执行build方法
      built = build();
      ...
      debugWidgetBuilderValue(widget, built);
    } catch (e, stack) {
      _debugDoingBuild = false;
      built = ErrorWidget.builder(
        _reportException(
          ErrorDescription('building $this'),
          e,
          stack,
          informationCollector: () => <DiagnosticsNode>[
            if (kDebugMode)
              DiagnosticsDebugCreator(DebugCreator(this)),
          ],
        ),
      );
    } finally {
      // We delay marking the element as clean until after calling build() so
      // that attempts to markNeedsBuild() during build() will be ignored.
      super.performRebuild(); // clears the "dirty" flag
    }
    try {
      _child = updateChild(_child, built, slot);
      assert(_child != null);
    } catch (e, stack) {
      built = ErrorWidget.builder(
        _reportException(
          ErrorDescription('building $this'),
          e,
          stack,
          informationCollector: () => <DiagnosticsNode>[
            if (kDebugMode)
              DiagnosticsDebugCreator(DebugCreator(this)),
          ],
        ),
      );
      _child = updateChild(null, built, slot);
    }
  }

ComponentElement-performRebuild メソッドは、StatelessWidget または State の build メソッドを呼び出し、Widget ツリーを更新するために使用されます。
try-catch を使用して例外をキャッチします。例外がキャッチされたら、ErrorWidget ポップアップ プロンプトを作成します。
ErrorWidget.builder は、例外表示のために _debugReportException メソッドによって返される FlutterErrorDetails を受け入れます。

FlutterErrorDetails _reportException(
  DiagnosticsNode context,
  Object exception,
  StackTrace? stack, {
  InformationCollector? informationCollector,
}) {
  //构建异常详情对象
  final FlutterErrorDetails details = FlutterErrorDetails(
    exception: exception,
    stack: stack,
    library: 'widgets library',
    context: context,
    informationCollector: informationCollector,
  );
  //报告异常
  FlutterError.reportError(details);
  return details;
}

FlutterError.reportError メソッドを通じて例外を報告する

  static void reportError(FlutterErrorDetails details) {
    onError?.call(details); //调用了onError回调
  }

onError は FlutterError の静的プロパティであり、デフォルトの処理メソッド dumpErrorToConsole があります。
自分で例外を報告したい場合は、カスタムのエラー処理コールバックを提供するだけで済みます。

  FlutterError.onError = (FlutterErrorDetails details) {
    reportError(details);
  };

その他の例外キャッチ

同期例外キャッチ

同期例外は try/catch を通じてキャッチできます。

  // 使用 try-catch 捕获同步异常
  try {
    throw StateError("xxx");
  } catch (e, stack) {
    print(e);
  }

非同期例外キャッチ

非同期例外は try/catch ではキャッチできません

try {
    Future.delayed(Duration(seconds: 1)).then((e) => Future.error("xxx"));
} catch (e) {
    print(e)
}

非同期例外をキャッチするには、Future が提供する catchError ステートメントを使用します。

// 使用 catchError 捕获异步异常
Future.delayed(Duration(seconds: 1))
    .then((e) => Future.error("xxx"))
    .catchError((e)=>print(e));

同期例外と非同期例外の両方を監視する方法はありますか?

ゾーンとプラットフォームディスパッチャー

ゾーンはコード実行の環境範囲を表します。異なるゾーンのコード コンテキストは異なり、相互に影響しません。コード実行サンドボックスと同様に、さまざまなサンドボックスが分離されています。サンドボックスは一部のコード動作をキャプチャ、インターセプト、または変更できます。たとえば、ゾーンはログ出力、タイマー作成、マイクロタスクのスケジュール動作をキャプチャできます。ゾーンは、未処理の例外をすべてキャプチャすることもできます。

  runZonedGuarded(() => runApp(MyApp()), (error, stack) {
    print(error);
  });

これは公式には推奨されなくなりました。PlatformDispatcher の方が推奨されます。

  PlatformDispatcher.instance.onError = (error, stack) {
    print(error);
    return true;
  };

例外をキャッチして報告する

void main() {
  var onError = FlutterError.onError; //先将 onerror 保存起来
  FlutterError.onError = (FlutterErrorDetails details) {
    onError?.call(details); //调用默认的onError处理
    reportError(details);
  };
  PlatformDispatcher.instance.onError = (error, stack) {
    reportError(error);
    return true;
  };
  runApp(const MyApp());
}

参考ドキュメント:
https://flutter.cn/docs/testing/errors

おすすめ

転載: blog.csdn.net/yuantian_shenhai/article/details/132895196