【问题标题】:How can I show alert dialog on base of a stream in case network request fails如果网络请求失败,如何在流的基础上显示警报对话框
【发布时间】:2021-03-08 07:49:05
【问题描述】:

这是我到目前为止的代码。 _mBlock.mSpotStream 是一个网络请求。 我很感兴趣如何在_mBlock.getSpots() 因网络错误而失败的情况下显示警报对话框,同时将列表保留在屏幕上。我尝试将警报对话框作为小部件返回,但在这种情况下我无法关闭它。

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(Strings.of(context).spot_list_title), centerTitle: true),
      body: Container(
          child: Column(
        children: [
          Expanded(
              child: Stack(
            children: [
              StreamBuilder<List<SpotDto>>(
                stream: _mBlock.mSpotStream,
                builder: (context, snapshot) {
                  return RefreshIndicator(
                    onRefresh: () {
                      return _mBlock.getSpots();
                    },
                    child: ListView.builder(
                      itemCount: snapshot.data?.length ?? 0,
                      itemBuilder: (context, position) {
                        return SpotListItem(snapshot.data[position], () {
                          ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(position.toString())));
                        });
                      },
                    ),
                  );
                },
              ),
              Column(
                children: [
                  Expanded(
                    child: StreamBuilder<Progress<bool>>(
                      stream: _mBlock.mStateStream,
                      builder: (context, snapshot) {
                        return Visibility(
                          visible: snapshot.data?.mIsLoading ?? false,
                          child: SizedBox.expand(
                            child: Container(
                              color: Colors.blue.withOpacity(Dimens.overlayOpacity),
                              child: Center(
                                child: CircularProgressIndicator(),
                              ),
                            ),
                          ),
                        );
                      },
                    ),
                  )
                ],
              )
            ],
          ))
        ],
      )),
    );
  }
}

showAlertDialog(BuildContext context, SpotListBlock block) {
  StreamBuilder<Error<String>>(
    stream: block.mErrorStream,
    builder: (context, snapshot) {
      if (snapshot.hasData) {
        return AlertDialog(
          title: Text(Strings.of(context).error),
          content: Text(snapshot.data.mErrorMessage),
          actions: [
            FlatButton(
              child: Text("Cancel"),
              onPressed: () {
                Navigator.pop(context, true);
              },
            )
          ],
        );
      } else {
        return Row();
      }
    },
  );
}

【问题讨论】:

    标签: flutter flutter-layout bloc


    【解决方案1】:

    最后,我已经这样修复了它,这是我能够修复它的唯一方法,感谢任何评论: 我的修复是基于这个要点https://gist.github.com/felangel/75f1ca6fc954f3672daf7962577d56f5

    class SpotListScreen extends StatelessWidget {
      final SpotListBlock _mBlock = SpotListBlock();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text(Strings.of(context).spot_list_title), centerTitle: true),
          body: Container(
              child: Column(
            children: [
              Expanded(
                  child: Stack(
                children: [
                  StreamBuilder<List<SpotDto>>(
                    stream: _mBlock.mSpotStream,
                    builder: (context, snapshot) {
                      return RefreshIndicator(
                        onRefresh: () {
                          return _mBlock.getSpots();
                        },
                        child: ListView.builder(
                          itemCount: snapshot.data?.length ?? 0,
                          itemBuilder: (context, position) {
                            return SpotListItem(snapshot.data[position], () {
                              ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(position.toString())));
                            });
                          },
                        ),
                      );
                    },
                  ),
                  StreamBuilder<Error<String>>(
                    stream: _mBlock.mErrorStream,
                    builder: (context, snapshot) {
                      if (snapshot.hasData) {
                        SchedulerBinding.instance.addPostFrameCallback((_) {
                          showDialog(
                            context: context,
                            barrierDismissible: false,
                            builder: (_) {
                              return Scaffold(
                                body: Center(
                                  child: RaisedButton(
                                    child: Text('dismiss'),
                                    onPressed: () {
                                      Navigator.pop(context);
                                    },
                                  ),
                                ),
                              );
                            },
                          );
                        });
                        return Container(
                          width: 0.0,
                          height: 0.0,
                        );
                      } else {
                        return Container(
                          width: 0.0,
                          height: 0.0,
                        );
                      }
                    },
                  ),
                  Column(
                    children: [
                      Expanded(
                        child: StreamBuilder<Progress<bool>>(
                          stream: _mBlock.mStateStream,
                          builder: (context, snapshot) {
                            return Visibility(
                              visible: snapshot.data?.mIsLoading ?? false,
                              child: SizedBox.expand(
                                child: Container(
                                  color: Colors.blue.withOpacity(Dimens.overlayOpacity),
                                  child: Center(
                                    child: CircularProgressIndicator(),
                                  ),
                                ),
                              ),
                            );
                          },
                        ),
                      )
                    ],
                  )
                ],
              ))
            ],
          )),
        );
      }
    }
    

    块代码

    Future<List<SpotDto>> getSpots() {
        var completer = new Completer<List<SpotDto>>();
        _reportsRepositoryImpl.getSpots().single.then((spotList) {
          addNewSpotsToList(spotList);
          completer.complete(spotList);
        }).catchError((Object obj) {
          switch (obj.runtimeType) {
            case DioError:
              _mErrorSink.add(Error((obj as DioError).message));
              completer.complete();
              break;
            default:
              completer.complete();
          }
          _mSpotSink.add(_mSpotList);
        });
    
        return completer.future;
      }
    

    【讨论】:

      【解决方案2】:

      显示警报对话框只是一个简单的调用,例如:

      await showDialog<bool>(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: 'alert!!!',
              content: 'hello world',
              actions: [
                  FlatButton(child: Text('cancel'), onPressed: () => Navigator.pop(context, false)),
                  FlatButton(child: Text('ok'), onPressed: () => Navigator.pop(context, true)),
              ],
            );
          },
        )
      

      当您拨打showDialog 时,屏幕上会显示一个对话框。

      【讨论】:

      • 但它会以这种方式将列表保留在屏幕上吗?此外,当我添加这样的对话框时,我无法使用 Navigator.pop(context, true) 丢失它
      • @Void 当然原始内容会出现在屏幕上。为什么 Navigator.pop 不能工作?能否请您提供更多详细信息?
      • 或者,有两件事我还是不明白。 1)我的对话框根据错误显示不同的内容(添加到问题中)2)不知道,为什么弹出不起作用,触发了onTap,但对话框留在屏幕上
      • @Void 请提供更多详细信息...例如你的完整代码
      • 谢谢,在您的帮助下,我终于能够描述这个问题,如果我在 StreamBuilder 中调用 showDialog,它会说它不是一个小部件,并且 streem 构建器应该返回一个小部件。所以我不能使用它,或者我应该以某种方式改变它。
      猜你喜欢
      • 1970-01-01
      • 2011-01-08
      • 2023-03-05
      • 2019-04-21
      • 1970-01-01
      • 2023-03-25
      • 2021-03-08
      • 1970-01-01
      相关资源
      最近更新 更多