Flutter底部导航栏页面数据传递及参数缺失报错解决
解决Flutter中Cart页面的构造函数参数错误及购物车数据共享问题
你遇到的1 positional argument(s) expected, but 0 found错误,根源很明确:Cart类的构造函数要求必须传入一个List<Dish>类型的参数,但在NavBar里创建Cart实例时,你直接写了Cart(),没有传入这个必填的参数。
不过这里还有个更深层的问题:原来的代码里,MyHomePage自己维护了_cartList,而NavBar里的Cart是一个全新的实例,两者的购物车数据完全隔离——也就是说,你在首页添加的商品,底部导航栏的购物车页面根本看不到。所以我们需要同时解决两个问题:参数缺失的报错,以及购物车数据在首页和购物车页面之间的共享。
下面是完整的修复方案:
1. 状态提升:将购物车数据移到NavBar中维护
把_cartList从MyHomePage移到NavBar的状态里,这样两个页面都能访问同一个数据源,保证数据同步。
修改NavBar.dart
import 'package:flutter/material.dart'; import 'package:sharewallpaper/cart.dart'; import 'package:sharewallpaper/main.dart'; import 'package:sharewallpaper/dish_object.dart'; class NavBar extends StatefulWidget { @override _NavBarState createState() => _NavBarState(); } class _NavBarState extends State<NavBar> { int _currentIndex = 0; // 把购物车列表移到这里统一维护 List<Dish> _cartList = []; // 提供给子页面的回调,用于更新购物车数据 void updateCart(Dish item) { setState(() { if (_cartList.contains(item)) { _cartList.remove(item); } else { _cartList.add(item); } }); } final List<Widget> _children = []; @override void initState() { super.initState(); // 初始化页面,传入必要的参数和回调 _children.addAll([ MyHomePage( title: "Home", cartList: _cartList, onCartUpdate: updateCart, ), Cart(cartList: _cartList, onCartUpdate: updateCart), ]); } void onTappedBar(int index) { setState(() { _currentIndex = index; }); } @override Widget build(BuildContext context) { return Scaffold( body: _children[_currentIndex], bottomNavigationBar: BottomNavigationBar( onTap: onTappedBar, currentIndex: _currentIndex, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')), BottomNavigationBarItem(icon: Icon(Icons.bookmark), title: Text('BookMark')), ], ), ); } }
2. 修改MyHomePage,接收外部的购物车数据和回调
原来的MyHomePage自己维护购物车,现在改成接收从NavBar传入的列表和更新回调,不再单独维护状态:
修改HomePage.dart
// 保留原有导入和Dish类定义 class MyHomePage extends StatefulWidget { final String title; final List<Dish> cartList; final Function(Dish) onCartUpdate; const MyHomePage({ Key? key, required this.title, required this.cartList, required this.onCartUpdate, }) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { List<Dish> _dishes = []; @override void initState() { super.initState(); _populateDishes(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), actions: <Widget>[ Padding( padding: const EdgeInsets.only(right: 16.0, top: 8.0), child: GestureDetector( child: Stack( alignment: Alignment.topCenter, children: <Widget>[ const Icon( Icons.shopping_cart, size: 36.0, ), if (widget.cartList.isNotEmpty) Padding( padding: const EdgeInsets.only(left: 2.0), child: CircleAvatar( radius: 8.0, backgroundColor: Colors.red, foregroundColor: Colors.white, child: Text( widget.cartList.length.toString(), style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 12.0, ), ), ), ), ], ), // 点击购物车图标时,切换到底部导航栏的购物车页面 onTap: () { if (widget.cartList.isNotEmpty) { final navBarState = context.findAncestorStateOfType<_NavBarState>(); navBarState?.onTappedBar(1); } }, ), ) ], ), body: _buildGridView(), ); } GridView _buildGridView() { return GridView.builder( padding: const EdgeInsets.all(4.0), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2), itemCount: _dishes.length, itemBuilder: (context, index) { var item = _dishes[index]; return Card( elevation: 4.0, child: Stack( fit: StackFit.loose, alignment: Alignment.center, children: <Widget>[ Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Icon( item.icon, color: (widget.cartList.contains(item)) ? Colors.grey : item.color, size: 100.0, ), Text( item.name, textAlign: TextAlign.center, style: Theme.of(context).textTheme.subhead, ) ], ), Padding( padding: const EdgeInsets.only(right: 8.0, bottom: 8.0), child: Align( alignment: Alignment.bottomRight, child: GestureDetector( child: (!widget.cartList.contains(item)) ? const Icon(Icons.add_circle, color: Colors.green) : const Icon(Icons.remove_circle, color: Colors.red), onTap: () { // 调用回调更新购物车,不再自己维护状态 widget.onCartUpdate(item); }, ), ), ), ], ), ); }, ); } // 保留原有_populateDishes方法 void _populateDishes() { var list = <Dish>[ Dish(name: 'Chicken Zinger', icon: Icons.fastfood, color: Colors.amber), Dish(name: 'Chicken Zinger without chicken', icon: Icons.print, color: Colors.deepOrange), Dish(name: 'Rice', icon: Icons.child_care, color: Colors.brown), Dish(name: 'Beef burger without beef', icon: Icons.whatshot, color: Colors.green), Dish(name: 'Laptop without OS', icon: Icons.laptop, color: Colors.purple), Dish(name: 'Mac wihout macOS', icon: Icons.laptop_mac, color: Colors.blueGrey), ]; setState(() { _dishes = list; }); } }
3. 修改Cart.dart,接收购物车数据和更新回调
让Cart也接收外部的购物车列表和更新回调,确保移除操作能同步到全局数据源:
修改Cart.dart
import 'package:flutter/material.dart'; import 'dish_object.dart'; class Cart extends StatefulWidget { final List<Dish> cartList; final Function(Dish) onCartUpdate; const Cart({ Key? key, required this.cartList, required this.onCartUpdate, }) : super(key: key); @override _CartState createState() => _CartState(); } class _CartState extends State<Cart> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Cart'), ), body: widget.cartList.isEmpty ? const Center(child: Text('Your cart is empty')) : ListView.builder( itemCount: widget.cartList.length, itemBuilder: (context, index) { var item = widget.cartList[index]; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 2.0), child: Card( elevation: 4.0, child: ListTile( leading: Icon(item.icon, color: item.color), title: Text(item.name), trailing: GestureDetector( child: const Icon(Icons.remove_circle, color: Colors.red), onTap: () { // 调用回调移除商品 widget.onCartUpdate(item); }, ), ), ), ); }, ), ); } }
方案说明
- 解决构造函数错误:现在创建
Cart实例时,我们传入了必填的cartList和onCartUpdate参数,编译器不会再报错。 - 数据实时同步:购物车数据由
NavBar统一维护,首页和购物车页面共用同一个列表,所有添加/移除操作都会实时同步到两个页面。 - 优化交互逻辑:点击首页AppBar的购物车图标时,会直接切换到底部导航栏的购物车页面,符合底部导航的交互习惯,避免页面栈混乱。
如果你的项目后续页面增多,也可以考虑使用Provider、Riverpod等状态管理库来管理购物车数据,代码会更简洁易维护。
内容的提问来源于stack exchange,提问作者Jeevan Crasta
相关产品推荐
相关产品推荐

