无法将 POST 请求从 Flutter 发送到 Firebase 实时数据库

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

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

enter image description here

enter image description here

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通信并且它有效,我从一个屏幕应用程序将信息添加到我的数据库中。我担心我的商店应用程序中有逻辑错误(很可能在我使用 addProduct 函数的屏幕上),所以我发布代码,如果您看到错误,请警告我。这是编辑产品屏幕,我在其中通过提供商使用 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
4个回答
1
投票
我认为您缺少实现等待。在尝试更改您的方法 Future 之后,您可以尝试在开始的 http.post 中添加等待吗?然后它就会起作用。

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


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


0
投票
实际上我也遇到了同样的问题,这听起来不是一个逻辑错误,我只创建了一个新项目,其中包含一个新的实时数据库,其位置与我的VPN不同,例如我的VPN设置为美国,所以我设置比利时的实时位置。我希望它也适合你。


0
投票
我是 Flutter 的新手,我也正在学习“Flutter & Dart - 完整指南 [2022 版]”课程。我那里也有同样的问题。如果您已经解决了,请指导我如何解决。

© www.soinside.com 2019 - 2024. All rights reserved.