Руководства

Корневая интеграция Flutter

Обработчики Flutter Framework и Platform внутри принадлежащей приложению Zone и показ через корневой Navigator.

v0.1.0-dev.1Средний уровень

Корневая интеграция Flutter

В руководстве один менеджер ядра подключается к трём корневым путям типичного Flutter-приложения: Zone приложения, отчётности Flutter Framework и необработанным ошибкам корневого Isolate через PlatformDispatcher. Для дочерних Isolate по-прежнему нужна отдельная явная привязка.

text
ошибка Zone ───────────────┐
FlutterError.onError ──────┼─→ одна цепочка ErrorManager
ошибка PlatformDispatcher ┘
01

Установите Flutter-пакет

shell
flutter pub add ark_error_manager_flutter:^0.1.0-dev.1

Пакет экспортирует публичный API ядра, поэтому файлу инициализации достаточно одного импорта.

02

Задайте владельца состояния инициализации

dart
final class ApplicationBootstrap {
  ErrorManager? _manager;
  FlutterErrorManagerBinding? _binding;

  void run() => runZonedGuarded(_start, _onZoneError);
}

Поле с типом, допускающим null, позволяет использовать прямой резервный путь, если ошибка возникла при создании самого менеджера.

03

Создайте и подключите объекты внутри Zone

dart
void _start() {
  WidgetsFlutterBinding.ensureInitialized();
  final navigatorKey = GlobalKey<NavigatorState>();

  final manager = ErrorManager(
    configuration: ErrorManagerConfiguration(
      environment: FlutterErrorBuildMode.environment(
        deployment: ErrorDeploymentEnvironment.production,
        application: const ErrorApplicationInfo(
          name: 'Example application',
          version: '1.0.0',
        ),
      ),
      classifiers: const <ErrorClassifier>[
        FlutterFrameworkErrorClassifier(),
      ],
      contextProviders: <ErrorContextProvider>[
        FlutterRuntimeErrorContextProvider(),
      ],
      reporters: const <ErrorReporter>[DeveloperLogErrorReporter()],
      presenter: NavigatorErrorPresenter(
        navigatorKey: navigatorKey,
        delegate: const ApplicationErrorPresentationDelegate(),
      ),
    ),
  );

  final binding = FlutterErrorManagerBinding(manager: manager)..attach();
  _manager = manager;
  _binding = binding;
  runApp(Application(navigatorKey: navigatorKey));
}
04

Обработайте ошибку создания менеджера

dart
void _onZoneError(Object error, StackTrace stackTrace) {
  final manager = _manager;
  if (manager == null) {
    Zone.root.handleUncaughtError(error, stackTrace);
    return;
  }
  manager.onUncaughtZoneError(error, stackTrace);
}

FlutterErrorManagerBinding и менеджер остаются у объекта инициализации. Виджеты, Presenter, UseCase, Repository и Provider их не получают.

05

Реализуйте принадлежащий приложению показ

dart
final class ApplicationErrorPresentationDelegate
    implements FlutterErrorPresentationDelegate {
  const ApplicationErrorPresentationDelegate();

  @override
  Future<void> present(
    BuildContext? context,
    ErrorIncident incident,
    ErrorPresentationDirective directive,
  ) async {
    if (context == null || directive == ErrorPresentationDirective.none) {
      return;
    }
    await showDialog<void>(
      context: context,
      barrierDismissible: directive != ErrorPresentationDirective.blocking,
      builder: (context) => const AlertDialog(
        title: Text('Произошла ошибка'),
        content: Text('Повторите операцию.'),
      ),
    );
  }
}

Delegate получает исходный локальный Incident, потому что может выбирать UI по Category, Severity и Policy. Не показывайте пользователю текст исключения, StackTrace или произвольные поля контекста.

06

Проверьте путь Flutter Framework

dart
FlutterError.reportError(
  FlutterErrorDetails(
    exception: StateError('Example framework failure'),
    stack: StackTrace.current,
    library: 'catalog example',
    context: ErrorDescription('while handling the example action'),
  ),
);

Используется штатный API отчётности Flutter. FlutterErrorManagerBinding получает ошибку через FlutterError.onError; экран не получает менеджер.

Владение при завершении

Мобильное приложение часто завершается вместе с процессом, но у тестов, Desktop Shell, встроенного Flutter Host и управляемого перезапуска есть настоящий порядок завершения:

dart
binding.detach();
await manager.flush();
await manager.close();

Сначала отключите привязку, чтобы глобальный обратный вызов не передал новый ErrorIncident во время закрытия. Сохраняйте объект привязки: он владеет ссылками на предыдущие обработчики и может безопасно восстановить их.

Исключите дублирование отчётов

Политика предыдущего Handler по умолчанию сохраняет штатную диагностику Flutter. Если прежний FlutterError.onError уже отправляет ошибки во внешнюю систему, определите единственного владельца удалённой отчётности. Два сохранённых внешних Reporter без дедупликации могут отправить одну ошибку дважды.

ARKTELOS

Инженерные системы для программного обеспечения, которое обязано выдерживать нагрузку.