Как эффективно перехватить указанное исключение, отобразить предупреждение и выйти из системы?

#flutter #exception #widget #flutter-web #bloc

#flutter #исключение #виджет #flutter-web #блок

Вопрос:

Веб-приложение содержит множество экранов со списковыми представлениями и диалоговыми окнами редактирования для редактирования выбранных записей. В представлении списка используется «стандартное поведение отображения» StreamBuilder .

Упрощенный bloc.dart

 class Bloc {
  final _subject = StreamController<Data>.broadcast();
  Stream<Data> get data => _subject.asyncMap(_getData);

  Future<Data> _getData(...) {
    try {
      final data = await api.getUrl(...);
      return data;
    } on SomeException catch (e) {
      // This exception is catched by StreamBuilder
      throw ApiException('could not get data');
    }
  }
}
 

Упрощенный widget.dart

 StreamBuilder<...>(
  stream: bloc.data,
  builder: (context, snapshot) {
    if (snapshot.hasError) {
      // Bloc throws an exception which thrown by API client (HttpClient).
      return ErrorWidget(snapshot.error.toString());
    }
    if (snapshot.hasData) {
      return ListView.builder(...);
    } else {
      return CircularProgressIndicator();
    }
  }
),
 

Каждое диалоговое окно редактирования используется showDialog для отображения сведений о выбранном элементе и сохранения изменений.
Может возникнуть ситуация, когда (например) токен доступа недействителен (или истек) во время его уже прошедшего проверку подлинности сеанса. Необходимо сообщить об этом пользователю (показав ему предупреждение) и после закрытия предупреждения уничтожить сеанс и вернуться к экрану входа в систему. Можно ли реализовать эффективное решение для перехвата конкретного исключения (например, TokenInvalidException ) в одном месте без добавления символьного кода, например:

 if (snapshot.error is TokenInvalidException) {
  // destroy session
  // return to Login
}
 

в каждое StreamBuilder представление списка и некоторый код, чтобы проверить, произошло ли исключение при каждом Dialog действии сохранения?

У меня 100500 экранов, и я не хочу реализовывать один и тот же код для каждого экрана. На самом деле мне нужен какой-то глобальный перехватчик исключений, который улавливает требуемое исключение и выполняет определенное действие.

Теперь я вижу некоторый глобальный StreamController поток с потоком, который принимает такое исключение (события) и прослушивается некоторым глобальным родительским виджетом (MaterialApp или, возможно, Main).

 final globalExceptionController = StreamController<TokenInvalidException>.broadcast();

// somewhere
globalExceptionController.stream.listen((e) async {
  // Show warning
  final result = await showDialog(...);
  // Go to login
  Navigator.pushReplacement(context, <login page route>);
}) {}

 

Проблема, которую я вижу здесь, заключается в том, что объект блока, который генерирует исключение, будет иметь сильную зависимость от контроллера потока, который ему абсолютно не интересен. Но на самом деле мне нужно как-то связать bloc и GUI потому, что для отображения предупреждения и переключения маршрута мне нужно context .

Любые идеи или критика приветствуются.

Комментарии:

1. snapshot.error — это объект, который вы можете проверить на тип среды выполнения, чтобы узнать, какая ошибка выдается, например if(error is FirebaseAuthException)

2. @Yadu, я это знаю. Вы прочитали мой вопрос?

Ответ №1:

Возможно, описанный здесь шаблон блока координатора поможет вам решить эту проблему