Я борюсь с RxDart (может быть, просто прямое программирование Rx). В настоящее время у меня есть виджет с состоянием, который вызывает мой блок в didChangeDependencies()
. Этот вызов выходит и получает данные через HTTP-запрос и добавляет их в поток. Я использую BehaviorSubject
, и это прекрасно работает. У меня есть дочерние виджеты, использующие StreamBuilders, и они получают данные без проблем. Моя проблема связана с ошибками. Если мой http-запрос не выполняется, я гидратирую поток с addError('whatever error')
, но StreamBuilder моего дочернего виджета не получает эту ошибку. Он ничего не получает вообще.
Итак, у меня есть несколько вопросов.
- Это ожидается?
- Не следует ли обрабатывать ошибки в 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 && plans.data.isNotEmpty) {
return ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: _buildPlanTiles(context, plans.data)
);
}
return Center(child: const CircularProgressIndicator());
}
);
}
}