#dart #flutter #bloc #rxdart
#dart #флаттер #блок #rxdart
Вопрос:
У меня проблемы с RxDart (возможно, просто прямое программирование Rx). В настоящее время у меня есть виджет с отслеживанием состояния, который вызывает мой блок в нем didChangeDependencies()
. Этот вызов завершается и получает данные через http-запрос и добавляет их в поток. Я использую BehaviorSubject
, и это работает нормально. У меня есть дочерние виджеты, использующие потоковые сборки, и они получают данные без проблем. Моя проблема связана с ошибками. Если мой http-запрос завершается неудачей, я увлажняю поток с помощью addError('whatever error')
, но потоковый модуль моего дочернего виджета не получает эту ошибку. Это вообще ничего не дает.
Итак, у меня есть несколько вопросов.
- Это ожидаемо?
- Не следует ли обрабатывать ошибки в StreamBuilder? В идеале, я хочу показать что-то в пользовательском интерфейсе, если что-то пойдет не так, поэтому не уверен, как еще это сделать.
- Я мог бы сделать свой дочерний виджет с отслеживанием состояния и использовать
stream.listen
. Я действительно получаю там ошибки, но это кажется излишним иметь это и StreamBuilder. - Я упускаю что-то фундаментальное здесь о потоках и обработке ошибок?
Вот мой блок:
final _plans = BehaviorSubject<List<PlanModel>>();
Observable<List<PlanModel>> get plans => _plans.stream;
fetchPlans() async {
try {
final _plans = await _planRepository.getPlans();
_plans.add(_plans);
}
on AuthenticationException {
_plans.addError('authentication error');
}
on SocketException {
_plans.addError('no network connection');
}
catch(error) {
_plans.addError('fetch unsuccessful');
}
}
Упрощенный родительский виджет:
class PlanPage extends StatefulWidget {
@override
PlanPageState createState() {
return new PlanPageState();
}
}
class PlanPageState extends State<PlanPage> {
@override
void didChangeDependencies() async {
super.didChangeDependencies();
var planBloc = BaseProvider.of<PlanBloc>(context);
planBloc.fetchPlans();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar( title: const Text('Your Plan') ),
body: PlanWrapper()
);
}
}
Упрощенный дочерний виджет с StreamBuilder:
class PlanWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
var planBloc = BaseProvider.of<PlanBloc>(context);
return StreamBuilder(
stream: planBloc.plans,
builder: (BuildContext context, AsyncSnapshot<List<PlanModel>> plans) {
if (plans.hasError) {
//ERROR NEVER COMES IN HERE
switch(plans.error) {
case 'authentication error':
return RyAuthErrorCard();
case 'no network connection':
return RyNetworkErrorCard();
default:
return RyGenericErrorCard(GeneralException().errorMessages()['message']);
}
}
if (plans.hasData amp;amp; plans.data.isNotEmpty) {
return ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: _buildPlanTiles(context, plans.data)
);
}
return Center(child: const CircularProgressIndicator());
}
);
}
}
Ответ №1:
По этому поводу была проблема в RxDart GitHub (https://github.com/ReactiveX/rxdart/issues/227 ). BehaviorSubjects не воспроизводили ошибки новым слушателям.
Это было исправлено в версии 0.21.0. «Критическое изменение: BehaviorSubject теперь будет выдавать ошибку, если последнее событие также было ошибкой. Раньше, когда ошибка возникала перед прослушиванием, подписчик не был уведомлен об этой ошибке.»