FutureBuilder不等待异步功能加载

时间:2020-05-17 02:11:30

标签: flutter dart

编辑3:这是现在的样子

n-1
  @override
  void initState() {
    super.initState();
    myFuture = genCode();
  }

打印

Future<Uint8List> genCode() async {
print('This should be the start')
Obj o = await _getAsyncData();
print('This should be the end');
return await scanner.generateBarCode(o.str);
}

Future<Obj> _getAsyncData() async {
Obj o = await addObj();
print('Hello');
print(o.str);
return o;
}

Future<Obj> addObj() async {
final String url = 'APIURL';
final client = new http.Client();
final response = await client.post(
url,
headers: {HttpHeaders.contentTypeHeader: 'application/json',
);
print('Obj added. Received response.');
Obj o = Obj.fromJSON(json.decode(response.body));
print(o.str);
return o;
}

FutureBuilder小部件直接进入此代码块

I/flutter (12991): This should be the start
I/flutter (12991): This should be the end
I/flutter (12991): Obj added. Received response.
I/flutter (12991): 12345
I/flutter (12991): Hello
I/flutter (12991): 12345

它显示感叹号并在屏幕上打印:

if (snapshot.hasError) {
children = <Widget>[
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
}

以某种方式忽略了异步功能仍在后台运行这一事实。

Error: NoSuchMethodError: The getter 'str' was called on null.
Receiver: null
Tried calling: str

原始代码:

错误:参数类型为'Future Function(BuildContext, 不能将AsyncSnapshot)'分配给参数类型'Widget Function(BuildContext,AsyncSnapshot)'。

我想念什么?代码与文档完全相同

FutureBuilder(
                  future: myFuture, // a previously-obtained Future<String> or null
                  builder: (BuildContext context, AsyncSnapshot snapshot) {
                    List<Widget> children;
                    if (snapshot.hasData) {
                      children = <Widget>[
                        QRDisplayWidget(title: '', bytes: snapshot.data),
                      ];
                    } else if (snapshot.hasError) {
                      children = <Widget>[
                        Icon(
                          Icons.error_outline,
                          color: Colors.red,
                          size: 60,
                        ),
                        Padding(
                          padding: const EdgeInsets.only(top: 16),
                          child: Text('Error: ${snapshot.error}'),
                        )
                      ];
                    } else {
                      children = <Widget>[
                        SizedBox(
                          child: CircularProgressIndicator(),
                          width: 60,
                          height: 60,
                        ),
                        const Padding(
                          padding: EdgeInsets.only(top: 16),
                          child: Text('Awaiting result...'),
                        )
                      ];
                    }
                    return Center(
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: children,
                      ),
                    );
                  },
                ),

编辑:所以我让FutureBuilder停止抛出错误,但是在获取数据之前仍会检索String值。

                FutureBuilder<String>(
                  future: getQRStr(), // a previously-obtained Future<String> or null
                  builder: (BuildContext context, AsyncSnapshot<String> snapshot) async {
                    List<Widget> children;
                    if (snapshot.hasData) {
                      children = <Widget>[
                        QRDisplayWidget(title: '', bytes: getBytes(snapshot)),
                      ];
                    } else if (snapshot.hasError) {
                      children = <Widget>[
                        Icon(
                          Icons.error_outline,
                          color: Colors.red,
                          size: 60,
                        ),
                        Padding(
                          padding: const EdgeInsets.only(top: 16),
                          child: Text('Error: ${snapshot.error}'),
                        )
                      ];
                    } else {
                      children = <Widget>[
                        SizedBox(
                          child: CircularProgressIndicator(),
                          width: 60,
                          height: 60,
                        ),
                        const Padding(
                          padding: EdgeInsets.only(top: 16),
                          child: Text('Awaiting result...'),
                        )
                      ];
                    }
                    return Center(
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: children,
                      ),
                    );
                  },
                ),

编辑2: 我将其编辑为现在的状态。如果在getBytes上使用Future,则得到 Future<String> getQRStr() async{ String str = await _asyncFetchData(); return Future.value(str); // return your response } Future<Uint8List> getBytes(AsyncSnapshot snapshot) async{ return await scanner.generateBarCode(snapshot.data); } 。删除Future使其运行时没有错误,但该应用似乎陷入了永久刷新的状态,不断调用getQRStr()。

在_asyncFetchData函数下,我有一个打印函数,该函数在成功检索数据后返回值之前将其打印出来。打印效果很好。但是FutureBuilder会显示返回的值为null。

2 个答案:

答案 0 :(得分:1)

您不能将Future传递给builder的{​​{1}}参数。 FutureBuilder中的任何内容都无法await

作为解决方案,您可以像下面那样创建一个新函数,并将其传递给builder

FutureBuilder

其他部分:

Future<Uint8List> genCode() async {
  return await scanner.generateBarCode(await getQRStr());
}

答案 1 :(得分:-1)

从代码中删除异步,然后重试。 但是在这种情况下,您需要处理QRDisplayWidget小部件,因为它具有字节等待功能,但是您可以在builder外部声明它,然后调用它,如下所示。

conda update --env