Flutter - 是否可以在不使用FutureBuilder的情况下从Future中提取数据?

时间:2018-05-11 15:56:32

标签: dart flutter

我正在阅读来自TextField的用户提供的输入(在这种情况下是邮政编码),我需要检查数据库的有效性。但是,我需要在提交按钮(在这种情况下为RaisedButtononPressed: () {} lambda函数内部进行异步数据库查询。在大多数编程语言中,这是一项相当简单和简单的任务。但是,我在Flutter中遇到的问题是,异步数据库查询返回的Future对象只能由FutureBuilder个对象使用,而这些对象只返回Widget对象。我只需要返回String,然后我可以使用它通过MaterialPageRoute对象传递到新路由,或者在不更改路由的情况下向用户显示错误。 Flutter有没有办法做到这一点?返回一个小部件对我来说没用,因为我不想创建一个新的Widget来显示。我正在使用Flutter 0.3.2和Dart 2.0.0

作为我需要调用数据库查询的简化示例:

@override
Widget build(Buildcontext context) {
    return new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
            new Container(
                padding: const EdgeInsets.all(16.0),
                child: new TextField(
                    keyboardType: TextInputType.number,
                    controller: _controller,
                    decoration: new InputDecoration(
                    hintText: 'Zip Code',
                ),
                onSubmitted: (string) {
                  return string;
                },
              ),
            ),
            new RaisedButton(
                onPressed: () {
                        // use regex to test against user input
                        if (_controller.text != null && _controller.text.isNotEmpty) {
                            RegExp zipCodeRegExp = new RegExp(r"^(\d{5})$");

                            // if the user input validates...
                            if (zipCodeRegExp.hasMatch(_controller.text)) {
                            zipCode = _controller.text;

                           // need to perform database query here and return a string, not a Widget

                            } else {
                               // an else condition here
                            }
                        } else {
                           // an else condition here
                        }
                    }
                }
            ),
        ],
    );
}

也许我没有遵循&#34;咒语&#34;颤动?感谢您对此的考虑和意见。

4 个答案:

答案 0 :(得分:7)

FutureBuilder只是一个方便的助手,可以在Future完成时重建小部件树。

您可以使用

funcThatReturnsFuture().then((result) {
  print(result);
  setState(() {
    someVal = result;
  })
})

Future funcThatMakesAsyncCall() async {
  var result = await funcThatReturnsFuture();
  print(result);  
  setState(() {
    someVal = result;
  })
}

主要限制是您无法在没有Future的情况下直接将值返回给调用者,因为无法从异步执行返回到同步执行。

答案 1 :(得分:2)

我已经弄明白了(我相信这就是君特最初所说的,但其根本原因当时并不清楚)。在不创建Future对象的情况下,能够使用Widget的唯一方法是使用Future API。 Future API允许解析Future对象,就好像它是AsyncSnapshot对象一样(在.data {{{{}} {{}} { 1}}功能)。这可以在返回的FutureBuilder对象上执行(可以builder:使用Future)。例如:

async

一旦您了解了如何利用await API,并且与使用Future regionName = dbClient.getRegionNameFromZipCode(int.parse(zipCode)); <-- this database method getRegionNameFromZipCode returns a Future object and uses async and await regionName.then((data) { String hZonesString = data[0]['hzone']; print(hZonesString); }, onError: (e) { print(e); }); 相比,这是非常简单的。很高兴知道这种语言的新手,比如我自己!

答案 2 :(得分:1)

Future只是回调的语义糖。想象一下你有:

void fetchName(void Function(String) callback);

void main() {
  fetchName((name) {
     print('Your name is: $name');
  });
}

name 转换(或提取fetchName的方式无法实现。在回调完成之前它不存在,并且回调可能不会立即完成(可以从数据库中读取,例如您的示例或网络等)。

使用FutureBuilder的一个优点是它真正有助于理解Future(和Stream的{​​{3}})之类的异步抽象,并让您专注于写作(同步)构建器代码:

new FutureBuilder<String>(
  future: _calculation, // a Future<String> or null
  builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none: return new Text('Press button to start');
      case ConnectionState.waiting: return new Text('Awaiting result...');
      default:
        if (snapshot.hasError)
          return new Text('Error: ${snapshot.error}');
        else
          return new Text('Result: ${snapshot.data}');
    }
  },
)

答案 3 :(得分:0)

您可以创建两种方法,一种方法是提取放入变量中的数据,另一种方法是像getter一样(在我的情况下,我需要使用插件 flutter_secure_storage 访问安全值,而无需使用 Futurebuilder

    Private Sub b_ok_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles b_ok.Click
        If b.Count = 0 OrElse t_search.Text = "" Then
            MessageBox.Show("please choose the customer", "warning ", MessageBoxButtons.OK, MessageBoxIcon.Error)
            b.RemoveFilter()
            t_search.Text = ""
            t_search.Focus()
            Exit Sub
        End If

        If frm.Name = "sales" Then
            t_search.Text = datagv.CurrentCell.Value
            sales.t_custom_id.Text = datagv.CurrentRow.Cells(0).Value
            sales.t_custom_name.Text = datagv.CurrentRow.Cells(1).Value

        End If
        Me.Close()

    End Sub