flutter - Flutter:当我抛出异常时,构建器在未来的构建器中调用了两次
问题描述
我试图在我未来的构建器上使用snackbar来显示错误。所以在initState方法上创建我未来的方法实例之后:
Future<DetailModel> futureDetail;
...
@override
void initState() {
futureDetail =
DetailProvider().detailProvider(widget.id);
super.initState();
}
在 futureBuilder 中,我使用如下:
Center(
child: SingleChildScrollView(
child: FutureBuilder(
future: futureDetail,
builder:
(context, AsyncSnapshot<DetailProductModel> snapshot) {
if (!snapshot.hasError ||
snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasData && snapshot.data.data != null) {
return Container();
}
if (snapshot.hasError &&
snapshot.error != null &&
snapshot.data == null) {
WidgetsBinding.instance.addPostFrameCallback((_) =>
showSnackbar(snapshot.error.toString(), context));
return Container();
} else {
return Center(
child: Text('failed to load'),
);
}
},
),
),
),
detailProvider
方法调用 http 服务,在我的示例中,我抛出 SocketException
生成器错误并显示快餐栏。
我知道未来的构建器是为每个状态显示一个小部件,但我想显示 snakbar。
但是builder被调用了两次并且snackbar显示了两次错误?snapshot.hasError and snapshot.error != null and snapshot.data == null
我在两次 build 中检查了这三个条件是否相同。我怎样才能防止显示两次 snakbar?
解决方案
更新:我分享的代码有问题。请检查一下。
首先,始终在 FutureBuilder 之外创建您的 SnackBar,因为 FutureBuilder 会不断被调用,因此会导致无限循环。你可以做的是使用 catchError。您仍然可以使用我们已经声明的变量在创建新的 SnackBar 之前检查是否存在活动的 SnackBar。
你会看到 SnackBar 只会显示一次,即使我在运行下面的代码时调用了三次。
应用相同的方式来更新您自己的代码:
class App extends StatefulWidget {
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
bool snackBarActive = false;
Future<String> futureDetail;
@override
void initState() {
futureDetail = Future<String>.error('An error Occurred').catchError((errText) {
showSnackBar(errText);
showSnackBar(errText);
showSnackBar(errText);
});
super.initState();
}
void showSnackBar(String errText) {
if (!snackBarActive) {
setState(() {
snackBarActive = true;
});
WidgetsBinding.instance.addPostFrameCallback((_) => Scaffold.of(context)
.showSnackBar(SnackBar(
content: Text(errText),
))
.closed
.whenComplete(() {
setState(() {
snackBarActive = false;
});
}));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: FutureBuilder(
future: futureDetail,
builder: (context, AsyncSnapshot<String> snapshot) {
if (!snapshot.hasError &&
snapshot.hasData &&
snapshot.data != null) {
return Container();
} else {
return Center(
child: Text('failed to load'),
);
}
},
),
),
),
);
}
}
推荐阅读
- python - 如何防止 python BeautifulSoup 用十六进制代码替换转义序列?
- optaplanner - 尝试在 Optaplanner 中启用多线程时没有已知的 workingObject
- php - SQL 错误访问论坛部分“查看您的帖子”
- jquery - 我无法将我在 jquery 中创建的按钮重定向到控制器
- python - 在 NetworkX 上使用广度优先搜索来查找前驱只为每个节点返回 1 个前驱
- swift - SwiftUI 中 Button 和 Image 的可点击区域
- python - 如何将数据输入到模型类的字段到html表?
- c# - 从服务调用 CloseMainWindow()
- javascript - 通过 Moment.js 以小时和分钟为单位的时差
- sockets - 所有 Socket 房间都会收到所有消息,即使它发送到一个房间