如果我在futurebuilder中收到错误,我想显示一个对话框。
如果收到错误消息,我想显示一个对话框并强迫用户单击按钮,以便可以将他重定向到另一页面。
问题似乎是在构建窗口小部件时无法显示对话框。
FutureBuilder(
future: ApiService.getPosts(),
builder: (BuildContext context, AsyncSnapshot snapShot) {
if (snapShot.connectionState == ConnectionState.done) {
if (snapShot.data.runtimeType == http.Response) {
var message =
json.decode(utf8.decode(snapShot.data.bodyBytes));
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text("Ok"),
onPressed: () => null",
)
],
);
});
}
return ListView.separated(
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: Colors.grey,
height: 1,
);
},
itemBuilder: (BuildContext context, int index) {
return _buildPostCard(index);
},
itemCount: snapShot.data.length,
);
return Center(
child: CircularProgressIndicator(),
);
},
)
如果我仅返回AlertDialog,它将起作用。但由于barrierDismissible属性,我需要showDialog。
有人知道这是否可能吗? 另外,这是处理我想要的东西的好方法吗?
谢谢
更新
为进一步参考,工作中的一位朋友提供了解决方案。
为了做我想要的,我必须决定将哪个未来传递给futureBuilder。
Future<List<dynamic>> getPostsFuture() async {
try {
return await ApiService.getPosts();
} catch (e) {
await showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text("Ok"),
onPressed: () => null",
)
],
);
});
}
}
}
然后在futureBuilder中,我会打电话
FutureBuilder(
future: getPostsFuture(),
谢谢
答案 0 :(得分:10)
为避免在使用setState() or markNeedsBuild() called during build
时出现showDialog
错误,请像这样将其包装到Future.delayed
中:
Future.delayed(Duration.zero, () => showDialog(...));
答案 1 :(得分:0)
builder
参数希望您返回Widget
。 showDialog是Future
。
所以你不能退货。
您将Dialog显示在其他窗口小部件的顶部,则无法从需要窗口小部件的构建方法中将其返回。
您想要的可以通过以下方式实现。
收到错误时,在UI上显示一个对话框,并为构建器返回一个容器。修改您的代码为此:
if (snapShot.data.runtimeType == http.Response) {
var message =
json.decode(utf8.decode(snapShot.data.bodyBytes));
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text("Ok"),
onPressed: () => null",
)
],
);
});
return Container();
}
答案 2 :(得分:0)
setState()或markNeedsBuild()。 允许使用此异常是因为该框架在子代之前构建父窗口小部件,这意味着将始终构建脏后代。否则,框架在此构建阶段可能不会访问此小部件。
因此,为了避免使用Future
回调,它会像这样EventQueue.
添加呼叫:
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Future futureCall() async {
await Future.delayed(Duration(seconds: 2));
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: futureCall(),
builder: (_, dataSnapshot) {
if (dataSnapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else {
Future(() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Employee Data'),
content: Text('Do you want to show data?'),
actions: <Widget>[
FlatButton(
onPressed: () =>
Navigator.of(context).pop('No'),
child: Text('NO')),
FlatButton(
onPressed: () =>
Navigator.of(context).pop('Yes'),
child: Text('YES'))
],
));
});
return Container();
}
},
);
}
}