Flutter:如何将GridView商品添加至列表并存储至API
实现步骤
1. 定义匹配需求的数据模型
先创建对应选中商品的模型类,贴合你需要的存储格式(可根据实际API要求调整字段):
class SelectedProduct { final String id; final String name; final double price; final int quantity; // 可选,若需要记录商品数量 SelectedProduct({ required this.id, required this.name, required this.price, this.quantity = 1, }); // 转成JSON格式,用于API传输 Map<String, dynamic> toJson() { return { 'id': id, 'name': name, 'price': price, 'quantity': quantity, }; } }
2. 管理页面状态
在你的GridView所在的StatefulWidget中,添加状态变量管理商品选中状态和已选商品列表:
class ProductGridViewPage extends StatefulWidget { const ProductGridViewPage({super.key}); @override State<ProductGridViewPage> createState() => _ProductGridViewPageState(); } class _ProductGridViewPageState extends State<ProductGridViewPage> { // 替换成你实际的商品数据源 final List<Map<String, dynamic>> _products = [ {'id': '1', 'name': '美式咖啡', 'price': 28.0}, {'id': '2', 'name': '经典汉堡', 'price': 45.0}, // 更多商品数据... ]; // 记录每个商品的选中状态,key为商品ID final Map<String, bool> _selectedStatus = {}; // 已选商品列表,用于最终提交API List<SelectedProduct> _selectedProducts = []; @override void initState() { super.initState(); // 初始化所有商品为未选中状态 for (var product in _products) { _selectedStatus[product['id']] = false; } }
3. 构建带选中功能的GridView Item
修改GridView的itemBuilder,添加复选框让用户选择商品,同时在页面底部添加全局的"Add to Menu"按钮:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('商品列表')), body: Column( children: [ Expanded( child: GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 16, mainAxisSpacing: 16, ), itemCount: _products.length, itemBuilder: (context, index) { final product = _products[index]; final isSelected = _selectedStatus[product['id']] ?? false; return Card( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(product['name'], style: const TextStyle(fontSize: 16)), Text('¥${product['price']}', style: const TextStyle(color: Colors.grey)), Checkbox( value: isSelected, onChanged: (value) { setState(() { _selectedStatus[product['id']] = value ?? false; }); }, ), ], ), ), ); }, ), ), // 底部的"Add to Menu"按钮 Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: ElevatedButton( onPressed: _addToMenu, child: const Text('Add to Menu'), ), ), ], ), ); }
4. 实现"Add to Menu"核心逻辑
编写方法将选中的商品添加到已选列表,支持去重或更新数量:
void _addToMenu() { setState(() { // 遍历所有商品,收集选中的项 for (var product in _products) { if (_selectedStatus[product['id']] == true) { // 检查商品是否已在列表中,存在则更新数量,不存在则添加新项 final existingIndex = _selectedProducts.indexWhere( (item) => item.id == product['id'], ); if (existingIndex != -1) { _selectedProducts[existingIndex] = SelectedProduct( id: product['id'], name: product['name'], price: product['price'], quantity: _selectedProducts[existingIndex].quantity + 1, ); } else { _selectedProducts.add( SelectedProduct( id: product['id'], name: product['name'], price: product['price'], ), ); } // 可选:添加后重置该商品的选中状态 _selectedStatus[product['id']] = false; } } }); // 提交已选列表到API _submitToApi(); }
5. 实现API提交逻辑
使用http包(需先在pubspec.yaml添加依赖:http: ^1.1.0)发送POST请求:
import 'package:http/http.dart' as http; import 'dart:convert'; Future<void> _submitToApi() async { // 替换成你的实际API接口地址 const apiUrl = 'https://your-api-domain.com/save-menu'; try { // 将已选商品列表转为JSON数组 final jsonData = _selectedProducts.map((item) => item.toJson()).toList(); final response = await http.post( Uri.parse(apiUrl), headers: {'Content-Type': 'application/json'}, body: jsonEncode(jsonData), ); if (response.statusCode == 200) { // 提交成功提示 if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('商品已成功添加到菜单')), ); } } else { // 处理提交失败 if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('提交失败:${response.statusCode}')), ); } } } catch (e) { // 处理网络错误 if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('网络错误:$e')), ); } } }
可选优化点
- 若需要单个商品点击直接添加,可将"Add to Menu"按钮放到每个GridView Item中,点击时直接将该商品加入列表并调用API。
- 根据API要求调整
toJson方法的字段,确保和后端接收格式一致。 - 提交API时添加加载状态,比如显示
CircularProgressIndicator,提升用户体验。
内容的提问来源于stack exchange,提问作者Aashi
相关产品推荐
相关产品推荐

