Flutter:当我抛出异常时,构建器在未来的构建器中调用了两次
Posted
技术标签:
【中文标题】Flutter:当我抛出异常时,构建器在未来的构建器中调用了两次【英文标题】:Flutter: Builder calls twice in future builder when i throw exception 【发布时间】:2020-08-14 10:06:48 【问题描述】:我正在尝试在我未来的构建器上使用小吃栏来显示错误。所以在 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
以在构建器上获取错误并显示小吃栏。
我知道未来的构建器是为每个状态显示一个小部件,但我想 显示蛇形条。
但是builder被调用了两次,并且snackbar显示了两次错误?
我在两次 build 中检查了这三个条件是否相同 snapshot.hasError and snapshot.error != null and snapshot.data == null
。如何防止显示两次 snakbar?
【问题讨论】:
如果您只是将print(snapshot);
作为构建器中的第一行,您会在日志上做什么?
paste.ubuntu.com/p/y99z2YJ8Rx@pskink
你的有状态小部件也被构建了两次?
这是完整的打印paste.ubuntu.com/p/Jmry3HxWcs@pskink
【参考方案1】:
更新:我分享的代码有问题。请检查一下。
首先,始终在 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'),
);
,
),
),
),
);
【讨论】:
以上是关于Flutter:当我抛出异常时,构建器在未来的构建器中调用了两次的主要内容,如果未能解决你的问题,请参考以下文章
当我尝试在调试控制台中构建 APK 以下显示时。构建:构建失败并出现异常
小部件库捕获的异常,在颤振中抛出以下断言构建答案**错误**