Почему дочерний виджет StreamBuilders не получает ошибок? - PullRequest
0 голосов
/ 31 марта 2019

Я борюсь с RxDart (может быть, просто прямое программирование Rx). В настоящее время у меня есть виджет с состоянием, который вызывает мой блок в didChangeDependencies(). Этот вызов выходит и получает данные через HTTP-запрос и добавляет их в поток. Я использую BehaviorSubject, и это прекрасно работает. У меня есть дочерние виджеты, использующие StreamBuilders, и они получают данные без проблем. Моя проблема связана с ошибками. Если мой http-запрос не выполняется, я гидратирую поток с addError('whatever error'), но StreamBuilder моего дочернего виджета не получает эту ошибку. Он ничего не получает вообще.

Итак, у меня есть несколько вопросов.

  1. Это ожидается?
  2. Не следует ли обрабатывать ошибки в StreamBuilder? В идеале я хочу показать что-то в пользовательском интерфейсе, если что-то пойдет не так, поэтому не уверен, как еще это сделать.
  3. Я мог бы сделать свой дочерний виджет с состоянием и использовать stream.listen. Я получаю ошибки там, но это кажется излишним иметь это и StreamBuilder.
  4. Я что-то упускаю здесь из-за потоков и обработки ошибок?

Вот мой блок:

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());
      }
    );
  }
}

1 Ответ

0 голосов
/ 31 марта 2019

В RxDart GitHub возникла проблема (https://github.com/ReactiveX/rxdart/issues/227). BehaviorSubjects не воспроизводили ошибки новым слушателям.

Это исправлено в версии 0.21.0. "Прерывание изменения: BehaviorSubject будетТеперь выдается ошибка, если последнее событие также было ошибкой. Раньше, когда ошибка возникла до прослушивания, подписчик не получал уведомление об этой ошибке. "

...