不好意思,我是Flutter的新手。
我正在做的课程正在练习,并且我遇到以下情况:
我有一个视图,其中可以使用方法getDataArray
(FutureBuilder
)使用Web服务,并且我只希望在访问此视图时仅执行一次。
我也有一个TextField
,FutureBuilder
,而TextField
在build()
中。我的widget
是StatefulWidget
,因为需要重绘它以显示我的TextField
的字符计数器,所以我认为这就是每次键入{{1} },然后再次调用build
。
我该如何解决?
FutureBuilder
答案 0 :(得分:4)
窗口小部件build()
方法中的任何内容都可以随时触发-这就是说,您不应依赖任何可能对其产生影响的关键因素。例如,打开键盘或关闭键盘就足以触发对小部件上的build()
的多次调用。
您的FutureBuilder
只是树上的一个小部件,因此,它在重建时(例如,每当您在TextField
上键入时)都将调用您的getDataArray()
因为它实际上并不真正知道它是否已经被调用。
如果只想一次将其命名为 ,则可以将其分配给州议员,然后将其分配给您的FutureBuilder
。只要该状态在小部件树上存在,就将被保留。
例如,如果您只想在每个状态生命周期中调用它,则可以在initState()
上进行分配;例如,如果您希望在依赖项发生变化时随时刷新该调用,可以在didChangeDependencies()
上进行分配。
class Pagina3State extends State<Pagina3> {
Future myFuture;
@override
void initState() {
myFuture = getDataArray();
}
@override
Widget build(BuildContext context) {
child: FutureBuilder(
future: myFuture,
)
}
}
答案 1 :(得分:1)
您可以创建一个返回futureBuilder的变量,因此,当您调用setState时,只有小部件可以重建,而变量则不需要,因此可以解决您的问题。
Widget futureWidget;
@override
void initState() {
futureWidget = FutureBuilder(
future: callme(),
builder: (_, sanpshot) {
print("future method call");
if (sanpshot.hasData) {
return Text(sanpshot.data.toString());
}
return CircularProgressIndicator();
},
);
super.initState();
}
callme() async {
await Future.delayed(Duration(seconds: 1));
return "success";
}
@override
Widget build(BuildContext context) {
print("build method call");
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
RaisedButton(
child: Text("press"),
onPressed: () {
setState(() {});
},
),
futureWidget,
],
),
);
}
答案 2 :(得分:0)
按照 Miguel 的建议,您应该将您的未来分配给 pip
范围之外的变量,以便它只运行一次。
请注意,从 Dart 2.0 开始,您可以使用 lazy initialization 和 late final variables 以更短的方式编写此代码:
build()
答案 3 :(得分:-1)
那是因为您在文本字段操作中使用了setstate,它会重建所有内容。我的一个应用程序也遇到了类似的问题,并且使用了bool来避免它,我将其命名为firstRun,如果确实是这样,那么我会在future builder中调用我的future函数,如果不是的话,我将其设为空,如ode示例下面。但是我不确定这是最好的方法,您还需要在某个地方(也许是在初始化状态)将该布尔值设为虚假;
bool firstRun = true;
@override
Widget build(BuildContext context) {...
...
onChanged: (valor) {
firstRun = false;
setState(() {
_input = valor;
});
},
.....
FutureBuilder(
future: firtRun ? getDataArray() : null,
builder: (...
答案 4 :(得分:-1)
问题的解决方案是在未来的构建器事件中添加延迟。 连接发生在待机期间,未触发 initstate
_initializeFirebase() async {
//ADD DURATION
await Future.delayed(Duration(seconds: 1));
return Firebase.initializeApp();
}
运行 Future Builder
return FutureBuilder(
// Initialize FlutterFire
future: _initializeFirebase(),
builder: (context, snapshot) {
// Check for errors
if (snapshot.hasError) {
return Center(
child: CircularProgressIndicator(),
);
}
// Once complete, show your application
if (snapshot.connectionState == ConnectionState.done) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Chat Application',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: SignScreen.routeName,
routes: {
SignScreen.routeName: (content) => SignScreen(),
ChatScreen.routeName: (content) => ChatScreen(),
LoginScreen.routeName: (content) => LoginScreen(),
RegisterScreen.routeName: (content) => RegisterScreen(),
});
}
// Otherwise, show something whilst waiting for initialization to complete
return Center(
child: CircularProgressIndicator(),
);
},
);