【问题标题】:Unhandled exception in FutureBuilder FlutterFutureBuilder Flutter 中未处理的异常
【发布时间】:2018-11-26 14:17:09
【问题描述】:

我尝试使用flutter 中的FutureBuilder 小部件从网络获取一些数据。为此,我使用以下代码:

Future<List<Product>> getWishList() async {
http.Response response = await http.post(
  MY_URL,
  headers: {
    HttpHeaders.acceptHeader: 'application/json',
    HttpHeaders.contentTypeHeader: 'application/json; charset=utf-8'
  },
);
if (response.statusCode == 200) {
  List<Product> ret = List();
  Map<String, dynamic> result;
  try {
    result = json.decode(response.body);
    for (var i = 0; i < result['data'].length; i++) {
        ret.add(Product.fromJson(result['data'][i]));
    }
    return ret;
  } catch (e) {
    return throw Exception("Json parse error");
  }
} else {
  return throw Exception("network connection failed");
}
}

与:

FutureBuilder(
            future: getWishList(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if(snapshot.connectionState == ConnectionState.done){
                  if(snapshot.hasError){
                    controller.forward(from: 0.0);
                    return Material(
                      child: Container(
                        margin: const EdgeInsets.only(top: 36.0),
                        width: double.infinity,
                        child: FadeTransition(
                          opacity: animation,
                          child: PButton(
                            onPressed: (){
                              setState(() {
                                getWishList();
                              });
                            },
                            child: Column(
                              children: <Widget>[
                                Icon(Icons.perm_scan_wifi,color: Colors.black,size: 76.0,),
                                SizedBox(height:24.0),
                                Text("Try again",style: TextStyle(fontSize: 16.0,color: const Color(0XFF222222)),),

                              ],
                            ),
                          ),
                        ),
                      ),
                    );
                  }else{
                    return new ListView(
                        children: <Widget>[
                          GestureDetector(
                              onTap:(){
                                setState(() {
                                  getWishList();
                                });
                              },
                              child: new Text("Every thing ok"))
                        ]);
                  }
              }else{
                return Center(
                  child: Container(
                      margin: const EdgeInsets.only(top: 36.0),
                      child: CircularProgressIndicator()),
                );
              }
            })

现在,如果 http 响应第一次返回错误,一切都很好,但点击 Try again,如果再次出现错误,控制台上会显示此消息:

[VERBOSE-2:shell.cc(184)] Dart 错误:未处理的异常:异常: 网络连接失败 _WishListState.getWishList(包:parchino/screen/screen_wish_list.dart:127:14) _WishListState.build... (包:parchino/screen/screen_wish_list.dart:65:33) State.setState (package:flutter/src/widgets/framework.dart:1130:30) _WishListState.build..(包:parchino/screen/screen_wish_list.dart:64:31) GestureRecognizer.invokeCallback(包:flutter/src/gestures/recognizer.dart:102:24) TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:242:9) TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:175:7) PrimaryPointerGestureRecognizer.handleEvent(包:flutter/src/gestures/recognizer.dart:315:9) PointerRouter._dispatch(包:flutter/src/gestures/pointer_router.dart

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    当您调用setState 时,您将小部件标记为脏,并且基本上告诉框架重新构建它,但仅在调用getWishList 之后(setState 内部的那个)。因为它是一个async 方法,所以它可以快速启动并重建小部件。

    通过重建小部件,您重建了试图评估其未来的FutureBuilder。由于 future 是一个函数,它调用它并对getWishList 进行新的调用。

    这对同一个方法进行了两次调用,因此对 http 服务器的两次调用非常快。这些调用可能存在冲突,并引发错误。

    您不应直接在FutureBuilder 中调用Future,而应使用previously-obtained Future

    Future<List<Product>> myFuture;
    
    @override
    void initState() {
      myFuture = getWishList();
      super.initState();
    }
    
    Future<List<Product>> getWishList() async {
     //Do your stuff
    }
    

    然后在您的构建中,将myFuture 设置为FutureBuilder 的未来,并在您的setState 中再次设置myFuture

    FutureBuilder(
      future: myFuture,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
          //...
          setState(() {
            myFuture = getWishList();
          });
          //...
      }
    );
    

    这将使setStatemyFuture 中设定一个新的未来,并要求小部件自行重建。作为FutureBuilder 重建,它评估myFuture 而不是再次调用http。

    【讨论】:

      猜你喜欢
      • 2019-07-02
      • 2023-04-03
      • 2023-03-13
      • 2021-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多