4

当我的提供者在http.get()通话期间出现问题时,我正在尝试将快照错误状态返回给我的 StreamBuilder。http.get()在我的情况下,当返回不同于 200(OK)的状态时,我会抛出异常。我希望能够将错误状态返回到快照并针对这种情况执行特定代码。现在,当我抛出异常时,应用程序就会崩溃。

提供者:

class FmsApiProvider {
  Future<List<FmsListResponse>> fetchFmsList() async {
    print("Starting fetch FMS..");
    final Response response = await httpGet('fms');
    if (response.statusCode == HttpStatus.ok) {
      // If the call to the server was successful, parse the JSON
      return fmsListResponseFromJson(response.body);
    } else {
      // If that call was not successful, throw an error.
      //return Future.error(List<FmsListResponse>());
      throw Exception('Failed to load FMSs');
    }
  }
}

存储库:

class Repository {
  final fmsApiProvider = FmsApiProvider();

  Future<List<FmsListResponse>> fetchAllFms() => fmsApiProvider.fetchFmsList();
}

集团:

class FmsBloc {
  final _fmsRepository = Repository();

  final _fmsFetcher = PublishSubject<List<FmsListResponse>>();

  Observable<List<FmsListResponse>> get allFms => _fmsFetcher.stream;

  fetchAllFms() async {
    List<FmsListResponse> itemModel = await _fmsRepository.fetchAllFms();
    _fmsFetcher.sink.add(itemModel);
  }

  dispose() {
    _fmsFetcher.close();
  }
}

我的流生成器​​:

StreamBuilder(
            stream: bloc.allFms,
            builder: (context, AsyncSnapshot<List<FmsListResponse>> snapshot) {
              if (snapshot.hasData) {
                return RefreshIndicator(
                    onRefresh: () async {
                      bloc.fetchAllFms();
                    },
                    color: globals.fcsBlue,
                    child: ScrollConfiguration(
                      behavior: NoOverScrollBehavior(),
                      child: ListView.builder(
                          shrinkWrap: true,
                          itemCount:
                              snapshot.data != null ? snapshot.data.length : 0,
                          itemBuilder: (BuildContext context, int index) {
                            final fms = snapshot.data[index];
                            //Fill a global list that contains the FMS for this instances
                            globals.currentFMSs.add(
                                FMSBasicInfo(id: fms.id, code: fms.fmsCode));
                            return MyCard(
                              title: _titleContainer(fms.fmsData),
                              fmsId: fms.id,
                              wmId: fms.fmsData.workMachinesList.first
                                  .id, //pass the firs element only for compose the image url
                              imageType: globals.ImageTypeEnum.iteCellLayout,
                              scaleFactor: 4,
                              onPressed: () => _onPressed(fms),
                            );
                          }),
                    ));
              } else if (snapshot.hasError) {
                return Text('Fms snapshot error!');
              }
              return FCSLoader();
            })

当抛出异常时,我想获得一个快照错误,然后只可视化我页面中的一个文本。

4

2 回答 2

8

您应该将 api 调用包装在 try catch 中,然后将错误添加到您的接收器。

class FmsBloc {
  final _fmsRepository = Repository();

  final _fmsFetcher = PublishSubject<List<FmsListResponse>>();

  Observable<List<FmsListResponse>> get allFms => _fmsFetcher.stream;

  fetchAllFms() async {
    try {
      List<FmsListResponse> itemModel = await _fmsRepository.fetchAllFms();
      _fmsFetcher.sink.add(itemModel);
    } catch (e) {
      _fmsFetcher.sink.addError(e);
    }
  }

  dispose() {
    _fmsFetcher.close();
  }
}
于 2019-06-20T12:38:16.270 回答
0

标记为正确的答案对我不起作用。进行一些调试时,我发现问题出现在捕获/抛出中:即使您在调试控制台中看到异常,您实际上也从未去过那里。

对我来说,在 Debug 中应用程序不会崩溃,但会在 Exception 上有一个断点,您可以使用 Play 按钮继续播放它。使用“运行”按钮,您可以在没有断点的情况下获得相同的行为(就像真正的用户一样)。

这是我的 BLoC 实现的流程:http 调用 -> 提供者 -> 存储库 -> bloc -> ui

我试图处理丢失互联网连接的情况,而不检查它并处理一般错误情况。

我的证据是throw Exception ('Error'); 在提供者中不会传播到流的右侧。我还尝试了其他方法,例如 try/catch,并将它们应用到代码的不同级别。

基本上我需要实现的是调用 fetcher.sink.addError('Error'); 但从发生错误的提供程序内部。然后在 UI 中检查 snapshot.hasError 将返回 true,并且错误可以很容易地处理。

这是唯一对我有用的(丑陋的)事情:在对提供者本身的调用中将接收器对象作为输入,并在 http 调用的 onCatchError() 函数中通过其函数将错误添加到接收器。

我希望它对某人有用。我知道这实际上不是最佳实践,但我只需要一个快速而肮脏的解决方案。如果有人有更好的解决方案/解释,我会很高兴地阅读评论。

于 2020-10-22T09:42:50.960 回答