简体   繁体   English

FutureBuilder Flutter中未处理的异常

[英]Unhandled exception in FutureBuilder Flutter

i try to use FutureBuilder widget in flutter to get some data from network. 我尝试在flutter使用FutureBuilder小部件从网络获取一些数据。 for this i use below code : 为此我使用下面的代码:

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");
}
}

AND: 和:

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

now if http response return error in first time every thing good but with click on Try again and if error again this message display on console: 现在,如果http响应在第一次返回错误,每件事情都好,但点击Try again ,如果再次出错,此消息显示在控制台上:

[VERBOSE-2:shell.cc(184)] Dart Error: Unhandled exception: Exception: network connection failed _WishListState.getWishList (package:parchino/screen/screen_wish_list.dart:127:14) _WishListState.build... (package:parchino/screen/screen_wish_list.dart:65:33) State.setState (package:flutter/src/widgets/framework.dart:1130:30) _WishListState.build.. (package:parchino/screen/screen_wish_list.dart:64:31) GestureRecognizer.invokeCallback (package: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 (package:flutter/src/gestures/recognizer.dart:315:9) PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart<…> [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 ..(package:parchino / screen / screen_wish_list.dart:64: 31)GestureRecognizer.invokeCallback(包:flutter / src / gestures / recognizer.dart:102:24)TapGestureRecognizer._checkUp(包:flutter / src / gestures / tap.dart:242:9)TapGestureRecognizer.handlePrimaryPointer(包:flutter / src / gestures / tap.dart:175:7)PrimaryPointerGestureRecognizer.handleEvent(package:flutter / src / gestures / recognizer.dart:315:9)PointerRouter._dispatch(package:flutter / src / gestures / pointer_router.dart <...>

When you call setState , you mark the widget as Dirty and basically tells the framework to rebuild it but only after getWishList has been called (the one inside setState ). 当你调用setState ,你将小部件标记为Dirty并且基本上告诉框架重建它,但只有在getWishList之后( setState那个)。 As it is an async method, it launches quickly and rebuild the widget. 由于它是async方法,因此可以快速启动并重建窗口小部件。

By rebuilding the widget, you rebuild the FutureBuilder which tries to evaluate its future. 通过重建窗口小部件,您可以重建FutureBuilder ,尝试评估其未来。 As the future is a function, it calls it and makes a new call to getWishList . 由于未来是一个函数,它调用它并对getWishList进行新的调用。

That makes two calls to the same method and thus two calls to an http server very quickly. 这使得两次调用相同的方法,因此两次调用http服务器非常快。 Those calls are probably in conflict, and throws an error. 这些调用可能存在冲突,并引发错误。

You should not invoke a Future directly in the FutureBuilder but use a previously-obtained Future instead. 您不应该直接在FutureBuilder调用Future ,而是使用以前获得的 Future

Future<List<Product>> myFuture;

@override
void initState() {
  myFuture = getWishList();
  super.initState();
}

Future<List<Product>> getWishList() async {
 //Do your stuff
}

Then in your build, set myFuture as the future of the FutureBuilder and in your setState , set myFuture again: 然后在你的构建中,将myFuture设置为FutureBuilder的未来,并在你的setState再次设置myFuture

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

That will make the setState set a new future in myFuture and ask the widget to rebuilt itself. 这将使setStatemyFuture设置一个新的未来,并要求小部件重建自己。 As the FutureBuilder rebuild, it evaluates myFuture instead of calling http once again. FutureBuilder重建时,它会评估myFuture而不是再次调用http。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM