error-handling - 如何在 flutter 中使用 bloc 模式进行错误处理?

想象一下,我正在使用一个 bloc 来处理网络请求。如果请求失败,处理失败的方式会因平台而异。在我的网络应用程序上,我想将用户重定向到错误页面,而在我的 IOS 应用程序上,我想显示一个对话框。

由于 bloc 应该只用于处理业务逻辑,而错误处理部分与业务逻辑无关,我们应该让 UI 部分负责错误处理。

UI 可以向 bloc 发送错误回调,并且 bloc 会在发生错误时运行它。我们还可以通过在不同平台发送不同的回调,以特定平台的方式处理错误。

然后是我的两个问题:

有更合适的方法吗?

如何将回调发送到 Bloc ?

在flutter中,我们只能在initState生命周期方法之后访问bloc(因为我们从builder上下文中获取bloc,它只在initState之后)。那么我们只能在 build 方法中发送回调。

这样,每次重建发生时,我们都会重复地向 bloc 发送回调(这些重复没有意义)。 使用 react,这样的一次性初始化可以在 componentDidMount 等生命周期中完成。 在 flutter 中,我们如何达到只运行一次这些初始化的目标?

最佳答案

这就是我们团队的处理方式:

首先我们像这样构建我们的主页(导航根):

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<SuspectEvent, SuspectState>(
        bloc: _bloc,
        builder: (context, state) {
          if (state.cameras.isEmpty) _bloc.dispatch(GetCamerasEvent());

          if (!_isExceptionHandled) {
            _shouldHandleException(
                hasException: state.hasException,
                handleException: state.handleException);
          }
        return Scaffold(
   ...

我们像这样声明 _shouldHandleException(仍然在主页上):

  _shouldHandleException(
      {@required bool hasException, @required Exception handleException}) {
    if (hasException) {
      if (handleException is AuthenticationException) {
        _isExceptionHandled = true;
        SchedulerBinding.instance.addPostFrameCallback((_) async {
          InfoDialog.showMessage(
                  context: context,
                  infoDialogType: DialogType.error,
                  text: 'Please, do your login again.',
                  title: 'Session expired')
              .then((val) {
            Navigator.popUntil(context, ModalRoute.withName('/'));
            this._showLogin();
          });
        });
      } else if (handleException is BusinessException) {
        _isExceptionHandled = true;
        SchedulerBinding.instance.addPostFrameCallback((_) async {
          InfoDialog.showMessage(
                  context: context,
                  infoDialogType: DialogType.alert,
                  text: handleException.toString(),
                  title: 'Verify your fields')
              .then((val) {
            _bloc.dispatch(CleanExceptionEvent());
            _isExceptionHandled = false;
          });
        });
      } else {
        _isExceptionHandled = true;
        SchedulerBinding.instance.addPostFrameCallback((_) async {
          InfoDialog.showMessage(
                  context: context,
                  infoDialogType: DialogType.error,
                  text: handleException.toString(),
                  title: 'Error on request')
              .then((val) {
            _bloc.dispatch(CleanExceptionEvent());
            _isExceptionHandled = false;
          });
        });
      }
    }
  }

在我们的街区我们有:


  @override
  Stream<SuspectState> mapEventToState(SuspectEvent event) async* {
    try {
      if (event is GetCamerasEvent) {

        ... //(our logic)
        yield (SuspectState.newValue(state: currentState)
          ..cameras = _cameras
          ..suspects = _suspects);
      }
      ... //(other events)
    } catch (error) {
      yield (SuspectState.newValue(state: currentState)
        ..hasException = true
        ..handleException = error);
    }
  }

在我们的错误处理中(在主页上),InfoDialog 只是一个 showDialog(来自 Flutter),它位于任何路由之上。所以只需要在根路由上调用警报即可。

https://stackoverflow.com/questions/52657042/

相关文章:

android - 没有权限(plugdev 组中的用户;你的 udev 规则错了吗?)

flutter - flutter 中带有圆角的警报对话框

dart - 转换时间戳

flutter - debugPaintSizeEnabled 在 Flutter 中不起作用

flutter - 如何在 Ios 上更改状态栏文本颜色

dart - 没有 AppBar 的 Flutter TabBar

text - 如何为 Text 小部件 Flutter 实现 OnPressed 回调

layout - flutter 中从右到左(RTL)

logging - Dart/flutter 错误 : 'toStringDeep' isn't d

android - Flutter:升级Play商店的版本代码