Flutter 捕获FutureBuilder调用的异步函数中的同步错误

Flutter 捕获FutureBuilder调用的异步函数中的同步错误,flutter,asynchronous,dart,nested,Flutter,Asynchronous,Dart,Nested,我有一个FutureBuilder小部件,它调用一个异步函数,用于从远程服务器获取给定设备可用的控件列表 FutureBuilder<List<Control>> buildControlList() { return FutureBuilder<List<Control>>( future: widget.server.getResponse(widget.device, widget.controlSet),

我有一个FutureBuilder小部件,它调用一个异步函数,用于从远程服务器获取给定设备可用的控件列表

FutureBuilder<List<Control>> buildControlList() {
    return FutureBuilder<List<Control>>(
        future: widget.server.getResponse(widget.device, widget.controlSet),
        builder:
            (BuildContext context, AsyncSnapshot<List<Control>> snapshot) {
          if (snapshot.hasData) {
            return buildList(buildControls(widget.controlSet, snapshot.data));
          } else if (snapshot.hasError) {
            Scaffold.of(context).showSnackBar(
                SnackBar(content: Text('${snapshot.error.toString()}')));
          }
          return const Center(child: CircularProgressIndicator());
        });
}
futurebuilderbuildcontrollist(){
回归未来建设者(
未来:widget.server.getResponse(widget.device,widget.controlSet),
建设者:
(BuildContext上下文,异步快照){
if(snapshot.hasData){
返回buildList(buildControls(widget.controlSet,snapshot.data));
}else if(snapshot.hasrerror){
Scaffold.of(上下文).showSnackBar(
SnackBar(内容:文本('${snapshot.error.toString()}'));
}
返回常量中心(子项:CircularProgressIndicator());
});
}
getResponse函数调用另一个async\u get函数,该函数构建并执行实际的api请求。收到响应后,它会将响应数据发送到同步函数,同步函数检查服务器报告的错误内容。如果找到一个,它将抛出自己的错误:

Future<List<Control>> getResponse(Device device, ControlSet controlSet,
  {Map<String, dynamic> params}) async {
    final String epoint = 'device/${device.name}/set/${controlSet.name}/';
    final http.Response response = await _get(epoint, params: params);
    _checkServerError(response); //synchronous check of response data
    final List<Control> values =
        json.decode(response.body).map<Control>((dynamic e) {
      return Control.fromJson(e);
    }).toList();
    return values;
}
未来的getResponse(设备、控制集、控制集、,
{Map params})异步{
最后一个字符串epoint='device/${device.name}/set/${controlSet.name}/';
final http.Response-Response=wait_-get(epoint,params:params);
_checkServerError(response);//同步检查响应数据
最终列表值=
decode(response.body).map((动态e){
返回控件.fromJson(e);
}).toList();
返回值;
}
_checkServerError函数非常简单。我已经尝试过同步和异步版本,似乎有相同的行为

void _checkServerError(http.Response response) {
    if (response.statusCode != 200) {
      final Map<String, dynamic> body = json.decode(response.body);
      if (body.containsKey('error')) {
        throw ServerException(
            statusCode: response.statusCode, errorMsg: body['error']);
      }
    }
}
void\u checkServerError(http.Response){
如果(response.statusCode!=200){
final-Map-body=json.decode(response.body);
if(body.containsKey('error')){
抛出服务器异常(
statusCode:response.statusCode,errorMsg:body['error']);
}
}
}
我似乎无法使抛出的ServerException传播到FutureBuilder的snapshot.hasError检查。我不想捕获错误并将其重新抛出到getResponse()函数中,尽管它看起来确实有效。将_checkServerError()更改为异步函数并等待它似乎也不起作用

为什么错误不会继续向上传到FutureBuilder

编辑:调用堆栈显示源自_checkServerError()并向上传播到buildControlList()内的FutureBuilder的错误。所以它正在到达那里。然而,FutureBuilder似乎没有捕捉到它并将其解释为一个错误的“快照”。也许我没有正确使用FutureBuilder?还有来自“未知来源”的信息。我不知道该怎么解释

调用堆栈:

Server._checkServerError (/mobile-client/lib/services/server.dart:75)
Server.getResponse (/mobile-client/lib/services/server.dart:112)
<asynchronous gap> (Unknown Source:0)
_ControlsScreen.buildControlList (/mobile-client/lib/screens/devices/controls.dart:71)
_ControlsScreen.build.<anonymous closure> (/mobile-client/lib/screens/devices/controls.dart:50)
Consumer.buildWithChild (/provider-4.0.5+1/lib/src/consumer.dart:175)
SingleChildStatelessWidget.build (/nested-0.0.4/lib/nested.dart:260)
StatelessElement.build (/lib/src/widgets/framework.dart:4576)
SingleChildStatelessElement.build (/nested-0.0.4/lib/nested.dart:280)
ComponentElement.performRebuild (/lib/src/widgets/framework.dart:4502)
Element.rebuild (/lib/src/widgets/framework.dart:4218)
StatelessElement.update (/lib/src/widgets/framework.dart:4583)
Element.updateChild (/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild (/lib/src/widgets/framework.dart:4527)
Element.rebuild (/lib/src/widgets/framework.dart:4218)
StatelessElement.update (/lib/src/widgets/framework.dart:4583)
Element.updateChild (/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild (/lib/src/widgets/framework.dart:4527)
Element.rebuild (/lib/src/widgets/framework.dart:4218)
ProxyElement.update (/lib/src/widgets/framework.dart:4862)
Element.updateChild (/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild (/lib/src/widgets/framework.dart:4527)
Element.rebuild (/lib/src/widgets/framework.dart:4218)
ProxyElement.update (/lib/src/widgets/framework.dart:4862)
Element.updateChild (/lib/src/widgets/framework.dart:3201)
RenderObjectElement.updateChildren (/lib/src/widgets/framework.dart:5522)
MultiChildRenderObjectElement.update (/lib/src/widgets/framework.dart:5957)
Element.updateChild (/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild (/lib/src/widgets/framework.dart:4527)
StatefulElement.performRebuild (/lib/src/widgets/framework.dart:4675)
Element.rebuild (/lib/src/widgets/framework.dart:4218)
StatefulElement.update (/lib/src/widgets/framework.dart:4707)
Element.updateChild (/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild (/lib/src/widgets/framework.dart:4527)
Element.rebuild (/lib/src/widgets/framework.dart:4218)
ProxyElement.update (/lib/src/widgets/framework.dart:4862)
Element.updateChild (/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild (/lib/src/widgets/framework.dart:4527)
StatefulElement.performRebuild (/lib/src/widgets/framework.dart:4675)
Server.\u checkServerError(/mobile-client/lib/services/Server.dart:75)
Server.getResponse(/mobileclient/lib/services/Server.dart:112)
(未知来源:0)
_ControlsScreen.buildControlList(/mobile client/lib/screens/devices/controls.dart:71)
_ControlsScreen.build。(/mobileclient/lib/screens/devices/controls.dart:50)
Consumer.buildWithChild(/provider-4.0.5+1/lib/src/Consumer.dart:175)
SingleChildStatelessWidget.build(/nested-0.0.4/lib/nested.dart:260)
statelement.build(/lib/src/widgets/framework.dart:4576)
SingleChildStatelement.build(/nested-0.0.4/lib/nested.dart:280)
ComponentElement.performRebuild(/lib/src/widgets/framework.dart:4502)
Element.rebuild(/lib/src/widgets/framework.dart:4218)
statelement.update(/lib/src/widgets/framework.dart:4583)
Element.updateChild(/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild(/lib/src/widgets/framework.dart:4527)
Element.rebuild(/lib/src/widgets/framework.dart:4218)
statelement.update(/lib/src/widgets/framework.dart:4583)
Element.updateChild(/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild(/lib/src/widgets/framework.dart:4527)
Element.rebuild(/lib/src/widgets/framework.dart:4218)
ProxyElement.update(/lib/src/widgets/framework.dart:4862)
Element.updateChild(/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild(/lib/src/widgets/framework.dart:4527)
Element.rebuild(/lib/src/widgets/framework.dart:4218)
ProxyElement.update(/lib/src/widgets/framework.dart:4862)
Element.updateChild(/lib/src/widgets/framework.dart:3201)
RenderObjectElement.updateChildren(/lib/src/widgets/framework.dart:5522)
MultiChildRenderObjectElement.update(/lib/src/widgets/framework.dart:5957)
Element.updateChild(/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild(/lib/src/widgets/framework.dart:4527)
StatefulElement.performRebuild(/lib/src/widgets/framework.dart:4675)
Element.rebuild(/lib/src/widgets/framework.dart:4218)
StatefulElement.update(/lib/src/widgets/framework.dart:4707)
Element.updateChild(/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild(/lib/src/widgets/framework.dart:4527)
Element.rebuild(/lib/src/widgets/framework.dart:4218)
ProxyElement.update(/lib/src/widgets/framework.dart:4862)
Element.updateChild(/lib/src/widgets/framework.dart:3201)
ComponentElement.performRebuild(/lib/src/widgets/framework.dart:4527)
StatefulElement.performRebuild(/lib/src/widgets/framework.dart:4675)

您是否完全确定正在引发异常?我觉得你的代码很标准。@ClaudioRedi是的,它肯定会抛出,因为应用程序会停止,调试器会显示源于_checkServerError()的异常。今天晚些时候将发布stacktrace唯一让我感到不安的是你如何使用未来。你能测试一下吗?1) 在生成器do
future中声明一个类级变量
FutureBuilder\u controlsFuture
2)重写方法
initState
和do
\u controlsFuture=widget.server.getResponse(widget.device,widget.controlSet)