Почему потоковые средства создания дочерних виджетов не получают ошибок?

#dart #flutter #bloc #rxdart

#dart #флаттер #блок #rxdart

Вопрос:

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

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

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