You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 15:24:53