为什么FutureBuilder被多次调用? [英] Why is FutureBuilder called multiple times?

查看:97
本文介绍了为什么FutureBuilder被多次调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不好意思,我是Flutter的新手.

Excuse the ignorance i am new to Flutter.

我正在做的课程正在练习,并且我遇到以下情况:

I am practicing on a course I did and I have the following scenario:

我有一个视图,其中可以使用方法 getDataArray ( FutureBuilder )使用Web服务,并且我只希望在访问该视图时仅执行一次

I have a view where I consume a web service in the method getDataArray (FutureBuilder), and I just want it to be done only once when this view is accessed.

我还有一个 TextField FutureBuilder ,并且 TextField build()中.我的 widget 是一个 StatefulWidget ,因为需要重绘它以显示我的 TextField 的字符计数器,所以我认为这是每个一次,当我键入 build 运行的内容并再次调用 FutureBuilder 时.

I also have a TextField, FutureBuilder and the TextField is in thebuild(). My widget is a StatefulWidget because it needs to be redrawn to show the character counter of my TextField, so I think this is the reason that every time I type something the build runs and call the FutureBuilder again.

我该如何解决?

    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());
                            }
                            }),
                    )
                    ],
                ),
                ),
            ),
            ),
        ),
        );
    }
    }

推荐答案

小部件的 build()方法中的任何内容都可以随时触发-这就是说,您不应依赖任何可能导致错误的关键信息.对它有影响.例如,打开键盘或关闭,足以触发对小部件上的 build()的多次调用.

Anything that's within a widget's build() method can trigger anytime — this is, you shouldn't rely on anything critical that could have impact on it. For example, opening a keyboard or closing, is enough to trigger multiple calls to build() on a widget.

您的 FutureBuilder 只是树上的一个小部件,因此,它在任何时候重建(例如,只要您在 TextField 上键入),它将调用您的 getDataArray(),因为它实际上并不真正知道该调用是否已被调用.

Your FutureBuilder is just a widget on your tree, and because of that, anytime it rebuilds (for example, whenever you type on the TextField), it will call your getDataArray() because it doesn't actually really knows if that has already been called or not.

如果只想一次将其命名为 ,则可以将其分配给状态成员,然后将其分配给 FutureBuilder .只要该状态在窗口小部件树上存在,就将保留该状态.

If you just want it to be called once, you can assign it to a state member and assign it to your FutureBuilder. That will be preserved as long as that state exists on the widget tree.

例如,如果您只想按状态生命周期调用它,则可以在 initState()上进行分配;例如,如果要刷新,则可以在 didChangeDependencies()上进行分配依赖项发生更改时随时调用.

You can for example assign it on initState() if you want to call it only per state lifecycle or at didChangeDependencies() for example, if you want to refresh that call anytime a dependency changes.

 class Pagina3State extends State<Pagina3> {
   Future myFuture;

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

  @override
   Widget build(BuildContext context) {

       child: FutureBuilder(
              future: myFuture,
      )
   }
}

这篇关于为什么FutureBuilder被多次调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆