推送数据到购物车;购物车总是显示是空的

问题描述 投票:0回答:1

我一直在尝试将购物车添加到我的咖啡应用程序中。当您按下“一次性购买”按钮时,不会将任何数据推送到购物车。我的小错误动画始终在模拟器中播放,并且购物车始终显示为空。

这是我的购物车型号:

import 'package:flutter/cupertino.dart';

class Cart {
  late final int? id;
  final String? productId;
  final String? productName;
  final int? initialPrice;
  final int? productPrice;
  final ValueNotifier<int>? quantity;
  final String? unitTag;
  final String? image;

  Cart(
      {required this.id,
      required this.productId,
      required this.productName,
      required this.initialPrice,
      required this.productPrice,
      required this.quantity,
      required this.unitTag,
      required this.image});

  Cart.fromMap(Map<dynamic, dynamic> data)
      : id = data['id'],
        productId = data['productId'],
        productName = data['productName'],
        initialPrice = data['initialPrice'],
        productPrice = data['productPrice'],
        quantity = ValueNotifier(data['quantity']),
        unitTag = data['unitTag'],
        image = data['image'];

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'productId': productId,
      'productName': productName,
      'initialPrice': initialPrice,
      'productPrice': productPrice,
      'quantity': quantity?.value,
      'unitTag': unitTag,
      'image': image,
    };
  }
}

这是我的产品型号:

class CoffeeItem {
  const CoffeeItem(
      {required this.id,
      required this.title,
      required this.image,
      required this.description,
      required this.image2,
      required this.quantity,
      required this.productPrice,
      required this.unit});

  final int id;

  final String title;
  final String image;
  final String description;
  final String image2;
  final int productPrice;
  final int quantity;
  final String unit;

  Map toJson() {
    return {
      'id': id,
      'title': title,
      'description': description,
      'price': productPrice,
      'image2': image2,
      'image': image,
      'quantity': quantity,
      'unit': unit,
    };
  }
}

这是我的项目列表,位于其自己的文件中:

import 'package:good_vibes_shop_app_2/models/coffeeitem.dart';

List<CoffeeItem> availableCoffees = [
  const CoffeeItem(
    id: 1,
    title: 'Roaster\'s Choice',
    image: 'lib/assets/Roasters_Choice.png',
    description:
        'Every delivery, you will receive a new and different surprise bean. This is for the coffee connoisseur that generally loves coffee no matter where it\'s from and how it\'s roasted.',
    image2: 'lib/assets/CostaRicaTub.png',
    productPrice: 15,
    quantity: 1,
    unit: '12oz',
  ),
  const CoffeeItem(
    id: 2,
    title: 'Brazil',
    image: 'lib/assets/Brazil.png',
    description:
        'Brazilian coffee is what started it all for Good Vibes and it still holds true to brewing a fantastic cup. This is our most lightly roasted coffee and has tasting notes of caramel with a little bit of nuttiness to it. This bean was grown in the Matas de Minas region of Brazil at an altitude of 1100m and was natural processed.',
    image2: 'lib/assets/Brazil Tub.png',
    productPrice: 15,
    quantity: 1,
    unit: '12oz',
  ),
  const CoffeeItem(
    id: 3,
    title: 'Colombia',
    image: 'lib/assets/Colombia.png',
    description:
        'Our Colombian coffee has the most traditional coffee flavor profile of any of our beans. It is chocolatey and robust; a perfect cup of morning Joe. These beans were grown in the Huila region of Colombia at altitudes of 1500m - 1900m.',
    image2: 'lib/assets/Colombia tub.png',
    productPrice: 15,
    quantity: 1,
    unit: '12oz',
  ),
  const CoffeeItem(
    id: 4,
    title: 'Indonesia',
    image: 'lib/assets/Indonesia.png',
    description:
        'These beans were grown in the Sumatra region of Indonesia and then were aged in their burlap sacks for 2 years after harvest. This aging process gives the coffee a savory, smoky tobacco flavor in your brew. This is a low acid cup of coffee for those of you struggling with reflux. Indonesia is one of the only (or possibly THE only) countries that uses a wet hulling process on their beans.',
    image2: 'lib/assets/Indo tub.png',
    productPrice: 15,
    quantity: 1,
    unit: '12oz',
  ),
  const CoffeeItem(
    id: 5,
    title: 'Zambia',
    image: 'lib/assets/Zambia.png',
    description:
        'Our Zambian coffee is probably our fruitiest in flavor, tasting mildly of citrus and toasted sugar. This bean was yellow honey processed, meaning that the beans retained much of their fruit mucilage during processing, then is dried on raised beds in the sun for up to 30 days. This coffee was grown in the Norther Province on the Isanya Estate at an altitude of over 1600m.',
    image2: 'lib/assets/Zambia tub.png',
    productPrice: 15,
    quantity: 1,
    unit: '12oz',
  ),
  const CoffeeItem(
    id: 6,
    title: 'Ethiopia',
    image: 'lib/assets/Ethiopia.png',
    description:
        'Our Ethiopian coffee tastes like raspberries and cream, but somehow isn\'t overly fruity like many African beans. This is probably partly due to the washed process and the way we roast the beans. An excellent brew; this is a great place to start for those who have never had an African coffee before.',
    image2: 'lib/assets/Ethiopia tub.png',
    productPrice: 15,
    quantity: 1,
    unit: '12oz',
  ),
];

这是我的 DBHelper:

import 'package:good_vibes_shop_app_2/widgets/checkoutscreens/cart/cart_model.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import 'dart:io' as io;

class DBHelper {
  static Database? _database;

  Future<Database?> get database async {
    if (_database != null) {
      return _database!;
    }
    _database = await initDatabase();
    return null;
  }

  initDatabase() async {
    io.Directory directory = await getApplicationDocumentsDirectory();
    String path = join(directory.path, 'cart.db');
    var db = await openDatabase(path, version: 1, onCreate: _onCreate);
    return db;
  }

// creating database table
  _onCreate(Database db, int version) async {
    await db.execute(
        'CREATE TABLE cart(id INTEGER PRIMARY KEY, productId VARCHAR UNIQUE, productName TEXT, initialPrice INTEGER, productPrice INTEGER, quantity INTEGER, unitTag TEXT, image TEXT)');
  }

// inserting data into the table
  Future<Cart> insert(Cart cart) async {
    var dbClient = await database;
    await dbClient!.insert('cart', cart.toMap());
    return cart;
  }

// getting all the items in the list from the database
  Future<List<Cart>> getCartList() async {
    var dbClient = await database;
    final List<Map<String, Object?>> queryResult =
        await dbClient!.query('cart');
    return queryResult.map((result) => Cart.fromMap(result)).toList();
  }

  Future<int> updateQuantity(Cart cart) async {
    var dbClient = await database;
    return await dbClient!.update('cart', cart.toMap(),
        where: "productId = ?", whereArgs: [cart.productId]);
  }

// deleting an item from the cart screen
  Future<int> deleteCartItem(int id) async {
    var dbClient = await database;
    return await dbClient!.delete('cart', where: 'id = ?', whereArgs: [id]);
  }
}

我的购物车提供商:

import 'package:flutter/cupertino.dart';
import 'package:good_vibes_shop_app_2/widgets/checkoutscreens/cart/cart_model.dart';

import 'package:good_vibes_shop_app_2/widgets/checkoutscreens/cart/db_helper.dart';
import 'package:shared_preferences/shared_preferences.dart';

class CartProvider with ChangeNotifier {
  DBHelper dbHelper = DBHelper();
  int _counter = 0;
  int _quantity = 1;
  int get counter => _counter;
  int get quantity => _quantity;

  double _totalPrice = 0.0;
  double get totalPrice => _totalPrice;

  List<Cart> cart = [];

  Future<List<Cart>> getData() async {
    cart = await dbHelper.getCartList();
    notifyListeners();
    return cart;
  }

  void _setPrefsItems() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setInt('cart_items', _counter);
    prefs.setInt('item_quantity', _quantity);
    prefs.setDouble('total_price', _totalPrice);
    notifyListeners();
  }

  void _getPrefsItems() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _counter = prefs.getInt('cart_items') ?? 0;
    _quantity = prefs.getInt('item_quantity') ?? 1;
    _totalPrice = prefs.getDouble('total_price') ?? 0;
  }

  void addCounter() {
    _counter++;
    _setPrefsItems();
    notifyListeners();
  }

  void removeCounter() {
    _counter--;
    _setPrefsItems();
    notifyListeners();
  }

  int getCounter() {
    _getPrefsItems();
    return _counter;
  }

  void addQuantity(int id) {
    final index = cart.indexWhere((element) => element.id == id);
    cart[index].quantity!.value = cart[index].quantity!.value + 1;
    _setPrefsItems();
    notifyListeners();
  }

  void deleteQuantity(int id) {
    final index = cart.indexWhere((element) => element.id == id);
    final currentQuantity = cart[index].quantity!.value;
    if (currentQuantity <= 1) {
      currentQuantity == 1;
    } else {
      cart[index].quantity!.value = currentQuantity - 1;
    }
    _setPrefsItems();
    notifyListeners();
  }

  void removeItem(int id) {
    final index = cart.indexWhere((element) => element.id == id);
    cart.removeAt(index);
    _setPrefsItems();
    notifyListeners();
  }

  int getQuantity(int quantity) {
    _getPrefsItems();
    return _quantity;
  }

  void addTotalPrice(double productPrice) {
    _totalPrice = _totalPrice + productPrice;
    _setPrefsItems();
    notifyListeners();
  }

  void removeTotalPrice(double productPrice) {
    _totalPrice = _totalPrice - productPrice;
    _setPrefsItems();
    notifyListeners();
  }

  double getTotalPrice() {
    _getPrefsItems();
    return _totalPrice;
  }
}

我的购物车屏幕:

// ignore_for_file: avoid_print

import 'package:badges/badges.dart';
import 'package:flutter/material.dart';
import 'package:good_vibes_shop_app_2/models/coffeeitem.dart';
import 'package:good_vibes_shop_app_2/widgets/checkoutscreens/cart/cart_model.dart';

import 'package:good_vibes_shop_app_2/widgets/checkoutscreens/cart/cart_provider.dart';
import 'package:provider/provider.dart';
import 'package:good_vibes_shop_app_2/widgets/checkoutscreens/cart/db_helper.dart';

class CartScreen extends StatefulWidget {
  const CartScreen(this.coffeeItem, this.availableCoffees, {Key? key})
      : super(key: key);

  final CoffeeItem coffeeItem;
  final List<CoffeeItem> availableCoffees;

  @override
  State<StatefulWidget> createState() => _CartScreenState();
}

class _CartScreenState extends State<CartScreen> {
  DBHelper? dbHelper = DBHelper();

  @override
  Widget build(BuildContext context) {
    final cart = Provider.of<CartProvider>(context);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.lime,
        title: const Text('Shopping Cart'),
        centerTitle: true,
        actions: [
          Center(
            child: Badge(
              showBadge: true,
              badgeContent: Consumer<CartProvider>(
                builder: ((context, value, child) {
                  return Text(
                    value.getCounter().toString(),
                    style: const TextStyle(color: Colors.white),
                  );
                }),
              ),
              animationType: BadgeAnimationType.fade,
              animationDuration: const Duration(milliseconds: 300),
              child: const Icon(Icons.shopping_bag_outlined),
            ),
          ),
          const SizedBox(width: 20.0),
        ],
      ),
      body: Column(
        children: [
          Expanded(
            child: Consumer<CartProvider>(
              builder: (BuildContext context, provider, widget) {
                if (provider.cart.isEmpty) {
                  return const Center(
                      child: Text(
                    'Your Cart is Empty',
                    style:
                        TextStyle(fontWeight: FontWeight.bold, fontSize: 18.0),
                  ));
                } else {
                  return ListView.builder(
                      shrinkWrap: true,
                      itemCount: provider.cart.length,
                      itemBuilder: (context, index) {
                        return Card(
                          color: Colors.blueGrey.shade200,
                          elevation: 5.0,
                          child: Padding(
                            padding: const EdgeInsets.all(4.0),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                              mainAxisSize: MainAxisSize.max,
                              children: [
                                Image(
                                  height: 80,
                                  width: 80,
                                  image:
                                      AssetImage(provider.cart[index].image!),
                                ),
                                SizedBox(
                                  width: 130,
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: [
                                      const SizedBox(
                                        height: 5.0,
                                      ),
                                      RichText(
                                        overflow: TextOverflow.ellipsis,
                                        maxLines: 1,
                                        text: TextSpan(
                                            text: 'Name: ',
                                            style: TextStyle(
                                                color: Colors.blueGrey.shade800,
                                                fontSize: 16.0),
                                            children: [
                                              TextSpan(
                                                  text:
                                                      '${provider.cart[index].productName!}\n',
                                                  style: const TextStyle(
                                                      fontWeight:
                                                          FontWeight.bold)),
                                            ]),
                                      ),
                                      RichText(
                                        maxLines: 1,
                                        text: TextSpan(
                                            text: 'Unit: ',
                                            style: TextStyle(
                                                color: Colors.blueGrey.shade800,
                                                fontSize: 16.0),
                                            children: [
                                              TextSpan(
                                                  text:
                                                      '${provider.cart[index].unitTag!}\n',
                                                  style: const TextStyle(
                                                      fontWeight:
                                                          FontWeight.bold)),
                                            ]),
                                      ),
                                      RichText(
                                        maxLines: 1,
                                        text: TextSpan(
                                            text: 'Price: ' r"$",
                                            style: TextStyle(
                                                color: Colors.blueGrey.shade800,
                                                fontSize: 16.0),
                                            children: [
                                              TextSpan(
                                                  text:
                                                      '${provider.cart[index].productPrice!}\n',
                                                  style: const TextStyle(
                                                      fontWeight:
                                                          FontWeight.bold)),
                                            ]),
                                      ),
                                    ],
                                  ),
                                ),
                                ValueListenableBuilder<int>(
                                    valueListenable:
                                        provider.cart[index].quantity!,
                                    builder: (context, val, child) {
                                      return PlusMinusButtons(
                                        addQuantity: () {
                                          cart.addQuantity(
                                              provider.cart[index].id!);
                                          dbHelper!
                                              .updateQuantity(Cart(
                                                  id: index,
                                                  productId: index.toString(),
                                                  productName: provider
                                                      .cart[index].productName,
                                                  initialPrice: provider
                                                      .cart[index].initialPrice,
                                                  productPrice: provider
                                                      .cart[index].productPrice,
                                                  quantity: ValueNotifier(
                                                      provider.cart[index]
                                                          .quantity!.value),
                                                  unitTag: provider
                                                      .cart[index].unitTag,
                                                  image: provider
                                                      .cart[index].image))
                                              .then((value) {
                                            setState(() {
                                              cart.addTotalPrice(double.parse(
                                                  provider
                                                      .cart[index].productPrice
                                                      .toString()));
                                            });
                                          });
                                        },
                                        deleteQuantity: () {
                                          cart.deleteQuantity(
                                              provider.cart[index].id!);
                                          cart.removeTotalPrice(double.parse(
                                              provider.cart[index].productPrice
                                                  .toString()));
                                        },
                                        text: val.toString(),
                                      );
                                    }),
                                IconButton(
                                    onPressed: () {
                                      dbHelper!.deleteCartItem(
                                          provider.cart[index].id!);
                                      provider
                                          .removeItem(provider.cart[index].id!);
                                      provider.removeCounter();
                                    },
                                    icon: Icon(
                                      Icons.delete,
                                      color: Colors.red.shade800,
                                    )),
                              ],
                            ),
                          ),
                        );
                      });
                }
              },
            ),
          ),
          Consumer<CartProvider>(
            builder: (BuildContext context, value, Widget? child) {
              final ValueNotifier<int?> totalPrice = ValueNotifier(null);
              for (var element in value.cart) {
                totalPrice.value =
                    (element.productPrice! * element.quantity!.value) +
                        (totalPrice.value ?? 0);
              }
              return Column(
                children: [
                  ValueListenableBuilder<int?>(
                      valueListenable: totalPrice,
                      builder: (context, val, child) {
                        return ReusableWidget(
                            title: 'Sub-Total',
                            value: r'$' + (val?.toStringAsFixed(2) ?? '0'));
                      }),
                ],
              );
            },
          )
        ],
      ),
      bottomNavigationBar: InkWell(
        onTap: () {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
              content: Text('Payment Successful'),
              duration: Duration(seconds: 2),
            ),
          );
        },
        child: Container(
          color: const Color.fromARGB(255, 36, 216, 219),
          alignment: Alignment.center,
          height: 50.0,
          child: const Text(
            'Proceed to Pay',
            style: TextStyle(
              fontSize: 18.0,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }
}

class PlusMinusButtons extends StatelessWidget {
  final VoidCallback deleteQuantity;
  final VoidCallback addQuantity;
  final String text;
  const PlusMinusButtons(
      {Key? key,
      required this.addQuantity,
      required this.deleteQuantity,
      required this.text})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        IconButton(onPressed: deleteQuantity, icon: const Icon(Icons.remove)),
        Text(text),
        IconButton(onPressed: addQuantity, icon: const Icon(Icons.add)),
      ],
    );
  }
}

class ReusableWidget extends StatelessWidget {
  final String title, value;
  const ReusableWidget({Key? key, required this.title, required this.value});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            title,
            style: Theme.of(context).textTheme.subtitle1,
          ),
          Text(
            value.toString(),
            style: Theme.of(context).textTheme.subtitle2,
          ),
        ],
      ),
    );
  }
}

这是我的单个项目屏幕,其中我的按钮是将数据推送到购物车:


class BeanScreen extends StatefulWidget {
  const BeanScreen(this.coffeeItem, this.availableCoffees, {Key? key})
      : super(key: key);

  final CoffeeItem coffeeItem;

  final List<CoffeeItem> availableCoffees;

  @override
  State<BeanScreen> createState() => _BeanScreen();
}

class _BeanScreen extends State<BeanScreen> {
  DBHelper? dbHelper = DBHelper();

  @override
  Widget build(BuildContext context) {
    final cart = Provider.of<CartProvider>(context);
    void saveData(int index) {
      dbHelper!
          .insert(
        Cart(
          id: index,
          productId: index.toString(),
          productName: availableCoffees[index].title,
          initialPrice: availableCoffees[index].productPrice,
          productPrice: availableCoffees[index].productPrice,
          quantity: ValueNotifier(1),
          unitTag: availableCoffees[index].unit,
          image: availableCoffees[index].image,
        ),
      )
          .then((value) {
        cart.addTotalPrice(availableCoffees[index].productPrice.toDouble());
        cart.addCounter();
        const snackBar = SnackBar(
          backgroundColor: Color.fromARGB(255, 113, 52, 255),
          content: Text('Item is added to cart'),
          duration: Duration(seconds: 1),
        );

        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      }).onError((error, stackTrace) {
        print(error.toString());
        const snackBar = SnackBar(
            backgroundColor: Color.fromARGB(255, 219, 56, 110),
            content: Text('Item is all sold out!'),
            duration: Duration(seconds: 1));

        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      });
    }

...

   
                          ElevatedButton(
                            style: ButtonStyle(
                                backgroundColor: MaterialStateProperty.all(
                                    const Color.fromARGB(255, 36, 194, 141))),
                            onPressed: () {
                              saveData(index);
                            },
                            child: const Text('One-Time Purchase'),
                          ),
                         

此外,我的图标徽章上的物品计数器不会随着按钮点击而更新数量。我确信这是因为没有任何东西添加到购物车中。我的程序还有更多内容,但这些都是与购物车有关的部分。

我已经把这个东西重写了好几次了。我尝试将

dbHelper!.insert
中的所有内容连接到我的 CoffeeItem 模型而不是我的 Cart 模型。我还在两个模型中更改并添加了信息,以尝试让它们更好地同步。这至少消除了一些错误,但仍然没有推送数据。

如有任何帮助,我们将不胜感激。

database flutter cart shopping-cart sqflite
1个回答
0
投票

我看到您正在尝试使用 Provider 包和 SQLite 数据库来存储数据,在 flutter 应用程序中实现购物车。在您的代码中,我可以看到您已经定义了模型、数据库助手和提供程序。但是,数据似乎没有按预期添加到购物车。

按照以下内容进行识别和修复: 确保您已正确初始化CartProviderDBHelper。您应该在应用程序的顶层执行此操作,通常在您的 main.dart 中: 无效主(){ 运行应用程序( 多提供商( 提供者:[ ChangeNotifierProvider(创建:(上下文)=> CartProvider()), ], 孩子:MyApp(), ), ); } 确保在整个应用程序中一致使用 CartProvider 和 DBHelper 实例。

我在您使用的 BeanScren 中看到 SaveData 函数。请确定 index 是 availableCoffess 列表的有效索引。你必须添加一个 打印语句以检查它是否正确识别为 选定的咖啡项目。

void saveData(int index) {
  if (index >= 0 && index < availableCoffees.length) {
    // Your code to add the item to the cart
    // ...
  } else {
    print("Invalid index: $index");
  }
}

确保您的 DBHelper 正常工作以将数据插入数据库。您还可以在此处使用打印语句或调试日志来检查是否正在调用插入方法以及是否正确插入数据。

  • CartScreen中,请确保您正确调用 getData 在屏幕加载时获取卡片数据。你应该有 调用 initState 方法或在屏幕首次显示时。

您可以在代码中使用 trycatch 异常。

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