通过try / catch接收到失败后,FutureBuilder不会更新

问题描述

我有FutureBuilder,它使将来来自HTTP GET请求。轻按提交按钮(也基于isInEditMode bool)初始化Future对象。

  • 我第一次点击Submit,它的connectionState从没有变为等待完成。
  • 让我们说Future会从Get请求中捕获错误,我可以将其优雅地放入catch块中,我会得到connectionState.done。
  • 现在问题出在第二次点击“提交”按钮上,这不会将future的connectionState更新为等待状态,因此,构建器也不会相应地显示在屏幕上。
  • 我已经检查过,每次我单击“提交”按钮时,都会从“获取”请求中检索到新的将来对象,但它不会反映在FutureBuilder中。如何让FutureBuilder知道Future对象已更新/更改,以适应新的对象?

class AddEditProductSoScreen extends StatefulWidget {
  static const routeName = '/add-edit-product';

  @override
  _AddEditProductSoScreenState createState() => _AddEditProductSoScreenState();
}

class _AddEditProductSoScreenState extends State<AddEditProductSoScreen> {
  var isEditMode = false;
  final _formKey = GlobalKey<FormState>();
  ProductFormModel _formProduct;
  Future<Response> futureOfSubmit;
  bool isLoadingVisible = false;

  @override
  Widget build(BuildContext context) {
    final productsProvider =
        Provider.of<ProductsProvider>(context,listen: false);
    Product product = ModalRoute.of(context).settings.arguments;
    if (product != null) {
      isEditMode = true;
      _formProduct = ProductFormModel.copyFromProduct(product);
    } else {
      _formProduct = ProductFormModel.init();
    }

    return Scaffold(
      bottomNavigationBar: Container(
        height: 50,child: Material(
          color: Theme.of(context).accentColor,child: InkWell(
            onTap: isLoadingVisible
                ? null
                : () {
                    if (isEditMode) {
                      futureOfSubmit =
                          productsProvider.editProduct(_formProduct);
                    } else {
                      futureOfSubmit =
                          productsProvider.addProduct(_formProduct);
                    }
                    isLoadingVisible = true;
                    futureOfSubmit.then((value) {
                      //Navigator.of(context).pop();
                    }).catchError((error) {
                      showDialog(
                          context: context,builder: (context) => AlertDialog(
                                title: Text('An error occurred!'),content: Text('Something went wrong.'),actions: [
                                  FlatButton(
                                      onpressed: () {
                                        Navigator.of(context).pop();
                                      },child: Text('Okay'))
                                ],));
                    }).whenComplete(() {
                      setState(() {
                        isLoadingVisible = false;
                      });
                    });
                  },child: FutureBuilder(
              future: futureOfSubmit,builder: (context,AsyncSnapshot<Response> snapshot) {
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return Align(
                    alignment: Alignment.center,child: Container(
                        height: 30,width: 30,child: CircularProgressIndicator(
                          backgroundColor: Colors.white,)),);
                } else {
                  return Container(
                    padding: EdgeInsets.all(10),width: double.infinity,child: Text(
                      'SUBMIT',style: TextStyle(color: Colors.white,fontSize: 20),textAlign: TextAlign.center,),);
                }
              },);
  }
}

任何帮助将不胜感激,谢谢!

编辑:这是productProvider类的addProduct方法,该方法会返回将来的对象,并且也会引发异常。

Future<Response> addProduct(ProductFormModel product) async {
    const url = '................';

    try {
      Response response = await http.post(url,body: json.encode({
            'title': product.title,'description': product.description,'imageUrl': product.imageUrl,'price': product.price,'isFavorite': product.isFav
          }));

      Map respMap = json.decode(response.body);
      product.id = respMap['name'];
      _items.add(product.toProduct());
      notifyListeners();
      return response;
    } on Exception catch (error) {
      print("error is :: " + error.toString());
      throw Exception('Something went wrong!!');
    }
  }

解决方法

要通知框架,小部件的状态已更改,可以使用setState的{​​{1}}方法。

所以这个:

StatefulWidget

应为:

futureOfSubmit = productsProvider.editProduct(_formProduct);

然后是其他人。

,

使用

setState((){});

通知框架状态已更改。

在If else块中使用setState

setState(() {
futureOfSubmit = productsProvider.editProduct(_formProduct);
 });