如果网络请求失败,如何在流的基础上显示警报对话框
Posted
技术标签:
【中文标题】如果网络请求失败,如何在流的基础上显示警报对话框【英文标题】: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();
,
);
【问题讨论】:
【参考方案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 构建器应该返回一个小部件。所以我不能使用它,或者我应该以某种方式改变它。以上是关于如果网络请求失败,如何在流的基础上显示警报对话框的主要内容,如果未能解决你的问题,请参考以下文章
在 App Delegate 中显示警报的方法失败,因为它的 rootViewController 不在 View Hierarcy 中