如何使用Provider重构Flutter餐食购物车应用代码?
用Provider重构Flutter餐食应用购物车逻辑
1. 安装Provider依赖
在项目的pubspec.yaml文件中添加Provider包:
dependencies: flutter: sdk: flutter provider: ^6.0.5 # 可替换为最新版本
执行flutter pub get完成依赖安装。
2. 创建购物车状态管理类
新建CartProvider类,继承ChangeNotifier来管理购物车状态,封装添加、删除、清空、计算总价等核心逻辑:
import 'package:flutter/material.dart'; import '../models/meal.dart'; // 替换为你项目中的餐品模型类 class CartProvider extends ChangeNotifier { final List<Meal> _cartItems = []; // 返回购物车副本,避免外部直接修改源数据 List<Meal> get cartItems => [..._cartItems]; // 添加餐品到购物车 void addItem(Meal meal) { _cartItems.add(meal); notifyListeners(); // 通知所有监听者状态更新 } // 从购物车删除指定餐品 void removeItem(Meal meal) { _cartItems.remove(meal); notifyListeners(); } // 清空购物车 void clearCart() { _cartItems.clear(); notifyListeners(); } // 计算购物车总价 double get totalPrice { return _cartItems.fold(0.0, (sum, meal) => sum + meal.price); } }
3. 在应用根节点注入Provider
修改main.dart,用ChangeNotifierProvider包裹根Widget,让整个应用都能访问购物车状态:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'providers/cart_provider.dart'; import 'screens/categories_screen.dart'; // 你的分类页面 void main() { runApp( ChangeNotifierProvider( create: (context) => CartProvider(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '餐食应用', home: const CategoriesScreen(), ); } }
4. 修改餐品页面的购物车操作逻辑
在餐品列表/详情页,将原来的购物车操作替换为调用CartProvider的方法:
// 餐品列表项的加入购物车按钮 ElevatedButton( onPressed: () { // listen: false 表示只修改状态,不监听变化 Provider.of<CartProvider>(context, listen: false).addItem(currentMeal); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('${currentMeal.name}已加入购物车')), ); }, child: const Text('加入购物车'), )
5. 重构购物车页面,实时监听状态变化
购物车页面需要实时同步购物车内容,通过Provider.of或Consumer监听状态变化:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/cart_provider.dart'; import '../models/meal.dart'; class CartScreen extends StatelessWidget { const CartScreen({super.key}); @override Widget build(BuildContext context) { final cartProvider = Provider.of<CartProvider>(context); final cartItems = cartProvider.cartItems; return Scaffold( appBar: AppBar(title: const Text('购物车')), body: cartItems.isEmpty ? const Center(child: Text('购物车是空的')) : Column( children: [ Expanded( child: ListView.builder( itemCount: cartItems.length, itemBuilder: (ctx, index) { final meal = cartItems[index]; return ListTile( title: Text(meal.name), subtitle: Text('¥${meal.price.toStringAsFixed(2)}'), trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () { Provider.of<CartProvider>(context, listen: false).removeItem(meal); }, ), ); }, ), ), Padding( padding: const EdgeInsets.all(16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( '总价:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), // 用Consumer包裹仅需更新的部件,避免整页重建 Consumer<CartProvider>( builder: (ctx, provider, child) { return Text( '¥${provider.totalPrice.toStringAsFixed(2)}', style: const TextStyle(fontSize: 18, color: Colors.red), ); }, ), ], ), ), ElevatedButton( onPressed: cartItems.isEmpty ? null : () { // 执行结算逻辑 Provider.of<CartProvider>(context, listen: false).clearCart(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('结算成功')), ); }, child: const Text('结算'), ), ], ), ); } }
内容的提问来源于stack exchange,提问作者Sena
相关产品推荐
相关产品推荐

