我很难弄清楚如何根据 subview “事件”更新 View 的一部分......让我解释一下:
我有一个由 Scaffold
组成的屏幕, 作为 body
一个自定义小部件,它调用一个 rest api 来获取要显示的数据(它使用一个 FutureBuilder ),然后它调度一个 Notification (它基本上包含了 Flutter 的 AsynchSnapshot )应该用来更新 floatingActionButton
(至少在我看来:P)。
这是build
画面方法:
@override
Widget build(BuildContext context) {
return NotificationListener<MyNotification>(
onNotification: onMyNotification,
child: Scaffold(
appBar: MyAppBar(),
body: MyRemoteObjectView(),
floatingActionButton: MyFloatingButton(),
),
);
}
View 完美呈现,数据从服务器检索并由
MyRemoteObjectView
显示并且通知已成功发送和接收,但我一调用 setState()
在我的回调中,我得到了异常:setState() or markNeedsBuild() called during build.
这是回调(在上述
build
方法的同一类中定义):bool onMyNotification(MyNotification notification) {
AsyncSnapshot snapshot = notification.snapshot;
if (snapshot.connectionState == ConnectionState.done) {
setState(() {
// these flags are used to customize the appearance and behavior of the floating button
_serverHasBeenCalled = true;
_modelDataRetrieved = snapshot.hasData;
});
}
return true;
}
这就是我发送通知的地方(
MyRemoteObjectView
状态的构建方法): @override
Widget build(BuildContext context) {
return FutureBuilder<T>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<T> snapshot) {
MyNotification(snapshot).dispatch(context);
// ...
重点是:如何和 当我应该告诉 Flutter 重绘 float 按钮(和/或其他小部件)吗? (因为当然没有
setState
我没有异常(exception)但按钮没有刷新)我弄错了整个事情吗?有更简单的方法吗?让我知道
最佳答案
FutureBuilder 构建完成后,它等待 future 返回一个值。完成后,您将调用 setState ,然后将再次构建 FutureBuilder 等等,从而导致无限的重绘循环。
您确定在这种情况下需要 FutureBuilder 和 NotificationListener 吗?您可能应该在 StatefulWidget 的 initState 中这样做:
@override
void initState() {
super.initState();
getData().then((data) {
setState(() {
_serverHasBeenCalled = true;
_modelDataRetrieved = true;
});
});
}
您还可以将 Future 存储在一个状态中并将其传递给 FutureBuilder。
关于Flutter 异常 `setState() or markNeedsBuild() called during build` 通过在 NotificationListener 回调中调用 setState,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58623919/