Flutter购物App:如何在CartPage中使用Points变量完成下单
问题描述
开发Flutter测试购物App时,无法在CartPage页面的「order now」按钮的onPressed回调中,使用Points页面内的_points变量来确认购买操作。
现有代码
CartModel
class CartModel extends ChangeNotifier { // list of items on sale final List _shopItems = const [ // [ itemName, itemPrice, imagePath, color ] ["Avocado", "4", "assets/images/avocado.png", Colors.green], ["Banana", "2", "assets/images/banana.png", Colors.yellow], ["pollo", "12", "assets/images/chicken.png", Colors.brown], ["acqua", "1", "assets/images/water.png", Colors.blue], ["mela", "3", "assets/images/mela.png", Colors.red], ["broccoli", "3", "assets/images/broccoli.png", Colors.brown], ]; final List _faidate = const [ ["Avocado", "14000", "assets/images/avocado.png", Colors.orange], ["Banana", "2", "assets/images/banana.png", Colors.blueGrey], ["pollo", "12", "assets/images/chicken.png", Colors.red], ["acqua", "1", "assets/images/water.png", Colors.blue], ]; // list of cart items final List _cartItems = []; get faidate => _faidate; get cartItems => _cartItems; get shopItems => _shopItems; // add item to cart void addItemToCart(int index) { _cartItems.add(_shopItems[index]); notifyListeners(); } // remove item from cart void removeItemFromCart(int index) { _cartItems.removeAt(index); notifyListeners(); } // calculate total price String calculateTotal() { double totalPrice = 0; for (int i = 0; i < cartItems.length; i++) { totalPrice += double.parse(cartItems[i][1].toString()); } return totalPrice.toStringAsFixed(2); } }
CartPage
class CartPage extends StatelessWidget { CartPage({ Key? key, }) : super(key: key); @override Widget build(BuildContext context) { Device.screenType == ScreenType.tablet; return Container( width: 100.w, height: 90.5.h, child: Container( width: 100.w, height: 20.5.h, child: Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, iconTheme: IconThemeData( color: Colors.grey[800], ), ), body: Consumer<CartModel>( builder: (context, value, child) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 24.0), child: Text( "Cart", style: GoogleFonts.notoSerif( fontSize: 36, fontWeight: FontWeight.bold, ), ), ), // list view of cart Expanded( child: Padding( padding: const EdgeInsets.all(12.0), child: ListView.builder( itemCount: (value.cartItems.length), padding: EdgeInsets.all(12), itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(12.0), child: Container( decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(8)), child: ListTile( leading: Image.asset( value.cartItems[index][2], height: 36, ), title: Text( value.cartItems[index][0], style: const TextStyle(fontSize: 18), ), subtitle: Text( '\points ' + value.cartItems[index][1], style: const TextStyle(fontSize: 12), ), trailing: IconButton( icon: const Icon(Icons.cancel), onPressed: () => Provider.of<CartModel>( context, listen: false) .removeItemFromCart(index), ), ), ), ); }, ), ), ), // total amount + pay now Padding( padding: const EdgeInsets.all(25.0), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: Colors.blueGrey[900]), padding: const EdgeInsets.all(24), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'total price', style: TextStyle(color: Colors.green[200]), ), const SizedBox(height: 8), Text( '\Points ${value.calculateTotal()}', style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), Container( padding: const EdgeInsets.all(1), child: Row( children: [ ElevatedButton( onPressed: () {}, child: const Text('order now')), ], ), ), ], ), ), ) ], ); }, ), ), ), ); } }
Points页面
class Points extends StatefulWidget { Points({Key? key,}) :super(key: key); _PointsState createState() => _PointsState(); } class _PointsState extends State<Points> { int _points = 0; @override void initState() { super.initState(); _loadPunti(); } _loadPunti() async { SharedPreferences prefs = await SharedPreferences.getInstance(); setState(() { _points = (prefs.getInt('points') ?? 0); }); } _savePunti() async { await FirebaseFirestore.instance.collection('xxxx').add({ 'Points': _points, }); } // other code... }
解决方案
核心问题是_points是Points页面的局部状态,无法直接跨页面访问。利用你已有的Provider状态管理方案,把积分状态迁移到全局的CartModel中,就能在CartPage直接调用。
步骤1:扩展CartModel管理积分
修改CartModel,添加积分相关的属性和方法:
class CartModel extends ChangeNotifier { // ... 原有代码保持不变 ... int _points = 0; get points => _points; // 加载积分 Future<void> loadPoints() async { SharedPreferences prefs = await SharedPreferences.getInstance(); _points = prefs.getInt('points') ?? 0; notifyListeners(); } // 保存积分到SharedPreferences和Firebase Future<void> savePoints() async { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setInt('points', _points); await FirebaseFirestore.instance.collection('xxxx').add({ 'Points': _points, }); notifyListeners(); } // 扣减积分(购买时调用) bool deductPoints(double total) { int totalInt = total.toInt(); if (_points >= totalInt) { _points -= totalInt; notifyListeners(); return true; } return false; } }
步骤2:修改CartPage的按钮逻辑
在order now按钮的onPressed中,获取积分并判断是否足够,处理购买流程:
// 替换原来的ElevatedButton部分 ElevatedButton( onPressed: () async { // 获取购物车总价 double total = double.parse(value.calculateTotal()); // 获取CartModel实例 final cartModel = Provider.of<CartModel>(context, listen: false); // 确保积分已加载 await cartModel.loadPoints(); // 判断积分是否足够 if (cartModel.deductPoints(total)) { // 积分足够,执行购买逻辑(比如清空购物车、保存积分) cartModel._cartItems.clear(); await cartModel.savePoints(); // 提示用户购买成功 ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('购买成功!')), ); } else { // 积分不足提示 ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('积分不足,无法完成购买')), ); } }, child: const Text('order now') ),
步骤3:更新Points页面使用全局积分
修改Points页面,不再使用局部状态,而是通过Provider获取CartModel的积分:
class Points extends StatelessWidget { // 改为StatelessWidget,状态由CartModel管理 const Points({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Consumer<CartModel>( builder: (context, cartModel, child) { return Scaffold( // 你的页面UI,直接使用cartModel.points body: Center( child: Text('当前积分:${cartModel.points}'), ), // 如果需要更新积分,调用cartModel的方法 floatingActionButton: FloatingActionButton( onPressed: () async { cartModel._points += 10; // 示例:增加积分 await cartModel.savePoints(); }, child: const Icon(Icons.add), ), ); }, ); } }
额外注意
- 确保在App启动时,初始化CartModel并加载积分,比如在
main.dart中:
void main() async { WidgetsFlutterBinding.ensureInitialized(); final cartModel = CartModel(); await cartModel.loadPoints(); runApp( ChangeNotifierProvider.value( value: cartModel, child: const MyApp(), ), ); }
内容的提问来源于stack exchange,提问作者sams
相关产品推荐
相关产品推荐

