【问题标题】:Can't send post requests from Flutter to Firebase Realtime Database无法从 Flutter 向 Firebase 实时数据库发送发布请求
【发布时间】:2022-06-26 13:37:05
【问题描述】:

我是 Flutter 初学者,我正在 Udemy 学习“Flutter & Dart - 完整指南 [2022 版]”课程(如果您知道我在第 10 节第 242 课“发送 POST 请求”的课程。这个这是我第一次使用 Firebase 和数据库,我在这个问题上停留了很长一段时间。我们在课程的前面部分构建了一个基本的商店应用程序,现在我们应该在添加时向我们的 Firebase 实时数据库发送一个 Post 请求一个新产品到我们的应用程序。我们应该在我们的数据库中添加一些关于产品的基本信息。当我尝试添加一个新产品时,没有任何反应,我的数据库中没有数据,我的应用程序中没有新产品(将产品添加到应用程序发生在发送 Post 请求后立即使用相同的功能)。我的终端没有错误,只有下面一行。

I/flutter (11699): ...

在添加 http 包和编写上一课的发布请求代码之前,我能够将产品添加到应用程序。这些是我的调试、数据库规则和发送 post 请求的函数。

void addProduct(Product product) {
    final url = Uri.parse(
        'https://flutter-update-ca55a-default-rtdb.firebaseio.com/products.json');

    http.post(
      url,
      body: json.encode({
        'title': product.title,
        'description': product.description,
        'imageUrl': product.imageUrl,
        'price': product.price,
        'isFavorite': product.isFavorite,
      }),
    );
    final newProduct = Product(
        id: DateTime.now().toString(),
        title: product.title,
        description: product.description,
        price: product.price,
        imageUrl: product.imageUrl);
    _items.add(newProduct);
    notifyListeners();
  }

我尝试了课程构造函数示例代码,但没有成功。然后我尝试禁用我的防火墙,将我的数据库规则更改为我的问题中看到的,仍然是同样的问题。我什至不知道我的代码是否正在与 firebase 通信。

编辑: 有时我也会在终端上获得最新的文本,并在下面添加屏幕截图:

Click to see Terminal SS

编辑 2: 所以我创建了一个空项目来查看我的计算机是否正在与 firebase 通信并且它工作正常,我从单屏应用程序将信息添加到我的数据库中。我担心我的 Shop 应用程序中有一个逻辑错误(很可能在我使用 addProduct 函数的屏幕上),所以如果您看到错误,我会发布代码,请警告我。这是edit-product-screen,我通过provider使用addProduct函数。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../providers/product.dart';
import '../providers/product_provider.dart';

class EditProductScreen extends StatefulWidget {
  static const String routeName = '/edit-product-screen';
  @override
  State<EditProductScreen> createState() => _EditProductScreenState();
}

class _EditProductScreenState extends State<EditProductScreen> {
  //final _priceFocusNode = FocusNode();
  //final _descriptionFocusNode = FocusNode();
  final _imageUrlController = TextEditingController();
  //final _imageUrlFocusNode = FocusNode();
  final _form = GlobalKey<FormState>();
  var _editedProduct =
      Product(id: '', title: '', description: '', price: 0, imageUrl: '');

  var _isInit = true;
  var _isloading = false;

  var _initValues = {
    'title': '',
    'description': '',
    'price': '',
    'imageUrl': '',
  };

  @override
  void initState() {
    //_imageUrlFocusNode.addListener(_updateImageUrl);
    super.initState();
  }

  @override
  void didChangeDependencies() {
    if (_isInit) {
      final String? productId =
          ModalRoute.of(context)!.settings.arguments as String?;
      if (productId != null) {
        _editedProduct = Provider.of<ProductProvider>(context, listen: false)
            .findbyID(productId);
        _initValues = {
          'title': _editedProduct.title,
          'description': _editedProduct.description,
          'price': _editedProduct.price.toString(),
          // 'imageUrl': _editedProduct.imageUrl,
          'imageUrl': '',
        };
        _imageUrlController.text = _editedProduct.imageUrl;
      }
    }
    _isInit = false;
    super.didChangeDependencies();
  }

  // @override
  // void dispose() {
  //   _imageUrlFocusNode.removeListener(_updateImageUrl);
  //    _priceFocusNode.dispose();
  //   _descriptionFocusNode.dispose();
  //   _imageUrlController.dispose();
  //   _imageUrlFocusNode.dispose();
  //   super.dispose();
  // }

  void _updateImageUrl() {
    // if (!_imageUrlFocusNode.hasFocus) {
    //   if ((!_imageUrlController.text.startsWith('http') &&
    //           !_imageUrlController.text.startsWith('https')) ||
    //       (!_imageUrlController.text.endsWith('.png') &&
    //           !_imageUrlController.text.endsWith('.jpg') &&
    //           !_imageUrlController.text.endsWith('.jpeg'))) {
    //     return;
    //   }
    setState(() {});
    //}
  }

  void _saveForm() {
    final isValid = _form.currentState!.validate();
    if (!isValid) {
      return;
    }
    _form.currentState!.save();
    setState(() {
      _isloading = true;
    });

    if (_editedProduct.id != null) {
      //var olan bir product editleniyor
      Provider.of<ProductProvider>(context, listen: false)
          .updateProduct(_editedProduct.id, _editedProduct);
      setState(() {
        _isloading = false;
      });
      Navigator.of(context).pop();
    } else {
      //yeni bir product oluşturuluyor.
      Provider.of<ProductProvider>(context, listen: false)
          .addProduct(_editedProduct)
          .catchError((error) {
        return showDialog<Null>(
          context: context,
          builder: (ctx) => AlertDialog(
            title: Text('An Error Occured'),
            content: Text(error.toString()),
            actions: [
              FlatButton(
                  onPressed: () {
                    Navigator.of(ctx).pop();
                  },
                  child: Text('Okay'))
            ],
          ),
        );
      }).then((_) {
        setState(() {
          _isloading = false;
        });
        Navigator.of(context).pop();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Edit Products'),
        actions: [
          IconButton(
            onPressed: _saveForm,
            icon: Icon(Icons.save),
          ),
        ],
      ),
      body: _isloading
          ? Center(
              child: CircularProgressIndicator(),
            )
          : Padding(
              padding: const EdgeInsets.all(16.0),
              child: Form(
                key: _form,
                child: ListView(
                  children: [
                    TextFormField(
                      initialValue: _initValues['title'],
                      decoration: InputDecoration(labelText: 'Title'),
                      validator: (value) {
                        if (value!.isEmpty) {
                          return 'Please enter a title';
                        }
                        return null;
                      },
                      textInputAction: TextInputAction.next,
                      // onFieldSubmitted: (_) {
                      //   FocusScope.of(context).requestFocus(_priceFocusNode);
                      // },
                      onSaved: (value) {
                        _editedProduct = Product(
                          title: value as String,
                          price: _editedProduct.price,
                          description: _editedProduct.description,
                          imageUrl: _editedProduct.imageUrl,
                          id: _editedProduct.id,
                          isFavorite: _editedProduct.isFavorite,
                        );
                      },
                    ),
                    TextFormField(
                      initialValue: _initValues['price'],
                      decoration: InputDecoration(labelText: 'Price'),
                      textInputAction: TextInputAction.next,
                      keyboardType: TextInputType.number,
                      //focusNode: _priceFocusNode,
                      // onFieldSubmitted: (_) {
                      //   FocusScope.of(context).requestFocus(_descriptionFocusNode);
                      // },
                      validator: (value) {
                        if (value!.isEmpty) {
                          return 'Please enter a price';
                        }
                        if (double.tryParse(value) == null) {
                          return 'Please enter a valid number';
                        }
                        if (double.parse(value) <= 0) {
                          return 'Plase enter a number greater than zero';
                        }
                        return null;
                      },
                      onSaved: (value) {
                        _editedProduct = Product(
                          title: _editedProduct.title,
                          price: double.parse(value as String),
                          description: _editedProduct.description,
                          imageUrl: _editedProduct.imageUrl,
                          id: _editedProduct.id,
                          isFavorite: _editedProduct.isFavorite,
                        );
                      },
                    ),
                    TextFormField(
                      initialValue: _initValues['description'],
                      decoration: InputDecoration(labelText: 'Description'),
                      maxLines: 3,
                      validator: (value) {
                        if (value!.isEmpty) {
                          return 'Please enter a description';
                        }
                        if (value.length < 10) {
                          return 'Your description must be longer then 10 characters';
                        }
                        return null;
                      },
                      textInputAction: TextInputAction.next,
                      //focusNode: _descriptionFocusNode,
                      keyboardType: TextInputType.multiline,
                      onSaved: (value) {
                        _editedProduct = Product(
                          title: _editedProduct.title,
                          price: _editedProduct.price,
                          description: value as String,
                          imageUrl: _editedProduct.imageUrl,
                          id: _editedProduct.id,
                          isFavorite: _editedProduct.isFavorite,
                        );
                      },
                    ),
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.end,
                      children: <Widget>[
                        Container(
                          width: 100,
                          height: 100,
                          margin: EdgeInsets.only(top: 8, right: 10),
                          decoration: BoxDecoration(
                            border: Border.all(width: 1, color: Colors.grey),
                          ),
                          child: _imageUrlController.text.isEmpty
                              ? Text('Enter a URL')
                              : FittedBox(
                                  child: Image.network(
                                    _imageUrlController.text,
                                    fit: BoxFit.cover,
                                  ),
                                ),
                        ),
                        Expanded(
                          child: TextFormField(
                            decoration: InputDecoration(labelText: 'Image URL'),
                            validator: (value) {
                              if (value!.isEmpty) {
                                return 'Please enter a image url';
                              }
                              if (!value.startsWith('http') &&
                                  !value.startsWith('https')) {
                                return 'Please enter a valid image url';
                              }
                              return null;
                            },
                            keyboardType: TextInputType.url,
                            textInputAction: TextInputAction.done,
                            controller: _imageUrlController,
                            //focusNode: _imageUrlFocusNode,
                            onFieldSubmitted: (_) {
                              _saveForm();
                            },
                            onSaved: (value) {
                              _editedProduct = Product(
                                title: _editedProduct.title,
                                price: _editedProduct.price,
                                description: _editedProduct.description,
                                imageUrl: value as String,
                                id: _editedProduct.id,
                                isFavorite: _editedProduct.isFavorite,
                              );
                            },
                          ),
                        ),
                      ],
                    )
                  ],
                ),
              ),
            ),
    );
  }
}

这是最新版的addProduct函数

   Future<void> addProduct(Product product) async {
    final url = Uri.parse(
        'https://flutter-update-ca55a-default-rtdb.firebaseio.com/products2.json');
    try {
      final response = await http.post(
        url,
        body: json.encode({
          'title': product.title,
          'description': product.description,
          'imageUrl': product.imageUrl,
          'price': product.price,
          'isFavorite': product.isFavorite,
        }),
      );
      print(json.decode(response.body));
      final newProduct = Product(
          id: DateTime.now().toString(),
          title: product.title,
          description: product.description,
          price: product.price,
          imageUrl: product.imageUrl);
      _items.add(newProduct);
      notifyListeners();
    } catch (error) {
      print(error);
      throw error;
    }
  }

【问题讨论】:

    标签: firebase flutter firebase-realtime-database


    【解决方案1】:

    我认为您缺少实现等待。在尝试更改您的方法 Future 之后,您能否尝试在开头的 http.post 添加 await 然后它会起作用。

    Future<Product> addProduct(Product product) async{
        final url = Uri.parse(
            'https://flutter-update-ca55a-default-rtdb.firebaseio.com/products.json');
    
        await http.post(
          url,
          body: json.encode({
            'title': product.title,
            'description': product.description,
            'imageUrl': product.imageUrl,
            'price': product.price,
            'isFavorite': product.isFavorite,
          }),
        );
    

    最后,您应该使用json to dart side 进行解析,并尝试使用工厂方法为您的模型实现 json 编码。 (我已经将我的第一篇文章添加到您的后端,请不要忘记为每个人更改写入规则)

    如果您想了解更多详细信息,请查看 dart.pad 样品:

    https://dartpad.dev/?id=c04e9842d98ac871988973df025c097e

    【讨论】:

    • 您好 vb10 感谢您抽出宝贵时间解决我的问题。我试过这些,但没有用。我在发送带有按钮的 http.post 时创建了一个空项目,它可以工作。恐怕我的代码某处有逻辑错误,可能在我正在使用 addProduct 函数的屏幕上。因此,如果我遗漏了什么,我将使用新代码和信息编辑我的问题,请告诉我。再次感谢您。
    【解决方案2】:

    也许这是迟到的答案,但这个问题也发生在我身上, if (_editedProduct.id != null) - 在这一行中你犯了一个错误,这应该是: if (_editedProduct.id != '') 希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-27
      • 1970-01-01
      • 2020-07-11
      • 2021-08-06
      • 1970-01-01
      • 2019-10-08
      相关资源
      最近更新 更多