为什么 FutureBuilder 被多次调用?

yav*_*avg 7 layout dart flutter

请原谅我是 Flutter 新手的无知。

我正在练习我做过的课程,我有以下情况:

我有一个视图,我在方法getDataArray( FutureBuilder) 中使用 Web 服务,我只想在访问此视图时只执行一次。

我也有一个TextFieldFutureBuilder并且TextFieldbuild(). My widgetis aStatefulWidget因为它需要重新绘制以显示 my 的字符计数器TextField,所以我认为这就是每次输入内容时build运行并FutureBuilder再次调用的原因。

我该如何解决?

    class Pagina3 extends StatefulWidget {
    @override
    Pagina3State createState() {
        return Pagina3State();
    }
    }

    class Pagina3State extends State<Pagina3> {
    String _input = "";

    //returns a web service
    Future getDataArray() async {
        final dynamic resp =
            await web.http_Web(webservices.url["DATOS"], "POST", {}, context);
        return resp;
    }

    Pagina3() {}

    @override
    Widget build(BuildContext context) {
        var validators = new Validators();
        var utils = new Utils();
        return Scaffold(
        appBar: AppBar(
            title: Text('Page 3'),
        ),
        body: SafeArea(
            child: Center(
            child: Form(
                child: Padding(
                padding: EdgeInsets.symmetric(horizontal: 10),
                child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                    TextFormField(
                        decoration: InputDecoration(
                        counter: Text('Letras ${_input.length.toString()}'),
                        icon: Icon(Icons.alternate_email),
                        hintText: 'ejemplo@correo.com',
                        labelText: 'Correo electrónico',
                        ),
                        validator: (value) => validators
                            .fn_checkValidation([validators.required(value)]),
                        onChanged: (valor) {
                        setState(() {
                            _input = valor;
                        });
                        },
                    ),
                    Container(
                        child: FutureBuilder(
                            future: getDataArray(),
                            builder: (context, AsyncSnapshot<dynamic> snapshot) {
                            if (snapshot.hasData) {
                                if (snapshot.data["ok"] == false) {
                                return Text("ha ocurrido un problema");
                                }
                                return (Text("Exito"));
                            } else {
                                return Center(child: CircularProgressIndicator());
                            }
                            }),
                    )
                    ],
                ),
                ),
            ),
            ),
        ),
        );
    }
    }
Run Code Online (Sandbox Code Playgroud)

Mig*_*ivo 13

小部件build()方法中的任何内容都可以随时触发——也就是说,您不应该依赖任何可能对其产生影响的关键内容。例如,打开键盘或关闭键盘就足以触发build()对小部件的多次调用。

FutureBuilder只是树上的一个小部件,因此,无论何时重建(例如,每当您键入TextField),它都会调用您的,getDataArray()因为它实际上并不真正知道它是否已经被调用。

如果你只想调用一次,你可以将它分配给一个 state 成员并将它分配给你的FutureBuilder. 只要该状态存在于小部件树上,它就会被保留。

例如,initState()如果您只想在每个状态生命周期中调用它,或者didChangeDependencies()例如,如果您想在依赖项更改时随时刷新该调用,则可以将其分配。

 class Pagina3State extends State<Pagina3> {
   Future myFuture;

  @override
  void initState() {
     myFuture = getDataArray();
  }

  @override
   Widget build(BuildContext context) {

       child: FutureBuilder(
              future: myFuture,
      )
   }
}

Run Code Online (Sandbox Code Playgroud)


Pom*_*m12 6

正如Miguel建议的那样,您应该将 future 分配给范围之外的变量build(),以便它只运行一次。

请注意,从 Dart 2.0 开始,您可以使用延迟初始化后期最终变量来以更短的方式编写此代码:

 class Pagina3State extends State<Pagina3> {
   late final Future myFuture = getDataArray();

   @override
   Widget build(BuildContext context) {
       child: FutureBuilder(
              future: myFuture,
      )
   }
}
Run Code Online (Sandbox Code Playgroud)