#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:
Возможно, описанный здесь шаблон блока координатора поможет вам решить эту проблему