Flutter购物清单开发:如何通过Provider带listId获取并刷新商品列表
解决思路
方案1:扩展现有ShoppingListProvider(快速适配)
直接在已有的Provider里新增商品相关状态和方法,复用现有实例,无需额外创建Provider:
- 修改
ShoppingListProvider,添加商品管理逻辑:
class ShoppingListProvider extends ChangeNotifier { List<ListModel> lists = []; final ShoppingListService service; // 新增:当前选中的清单ID和对应商品列表 int? _selectedListId; List<ItemModel> _items = []; ShoppingListProvider(this.service); int? get selectedListId => _selectedListId; List<ItemModel> get items => _items; Future<void> init() async { lists = await service.getLists(); notifyListeners(); } // 选中清单并拉取对应商品 Future<void> selectListAndFetchItems(int listId) async { _selectedListId = listId; _items = await service.getItems(listId); notifyListeners(); } // 刷新当前选中清单的商品 Future<void> refreshCurrentItems() async { if (_selectedListId == null) return; _items = await service.getItems(_selectedListId!); notifyListeners(); } }
- 清单列表页面的
ListTile点击事件调用方法:
ListTile( title: Text(list.name), onTap: () { provider.selectListAndFetchItems(list.id); Navigator.push(context, MaterialPageRoute( builder: (context) => ItemListPage() )); }, )
- 商品页面使用
RefreshIndicator:
Widget build(BuildContext context) { final provider = Provider.of<ShoppingListProvider>(context); return Scaffold( body: RefreshIndicator( onRefresh: provider.refreshCurrentItems, child: ListView.builder( itemCount: provider.items.length, itemBuilder: (context, index) { return ListTile(title: Text(provider.items[index].name)); }, ), ), ); }
方案2:创建独立的ItemProvider(职责分离)
如果希望Provider职责更单一,专门创建管理商品数据的Provider,通过路由参数传递listId:
- 创建
ItemProvider:
class ItemProvider extends ChangeNotifier { final ShoppingListService service; int? _listId; List<ItemModel> _items = []; ItemProvider(this.service); List<ItemModel> get items => _items; // 设置清单ID并拉取商品 Future<void> setListIdAndFetch(int listId) async { _listId = listId; _items = await service.getItems(listId); notifyListeners(); } // 刷新当前清单的商品 Future<void> refreshItems() async { if (_listId == null) return; _items = await service.getItems(_listId!); notifyListeners(); } }
- 清单列表页面跳转时传递
listId:
onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => ItemListPage(listId: list.id) )); }
- 商品页面初始化时调用Provider方法:
class ItemListPage extends StatefulWidget { final int listId; const ItemListPage({required this.listId, super.key}); @override State<ItemListPage> createState() => _ItemListPageState(); } class _ItemListPageState extends State<ItemListPage> { @override void initState() { super.initState(); final itemProvider = Provider.of<ItemProvider>(context, listen: false); itemProvider.setListIdAndFetch(widget.listId); } @override Widget build(BuildContext context) { final itemProvider = Provider.of<ItemProvider>(context); return Scaffold( body: RefreshIndicator( onRefresh: itemProvider.refreshItems, child: ListView.builder( itemCount: itemProvider.items.length, itemBuilder: (context, index) { return ListTile(title: Text(itemProvider.items[index].name)); }, ), ), ); } }
方案3:使用ChangeNotifierProxyProvider(联动更新)
如果需要清单选中状态变化时自动更新商品数据,用ProxyProvider关联两个Provider:
- 在
main.dart的MultiProvider中配置:
MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => ShoppingListProvider(service)), ChangeNotifierProxyProvider<ShoppingListProvider, ItemProvider>( create: (context) => ItemProvider(service), update: (context, listProvider, itemProvider) { // 选中清单ID变化时自动刷新商品 if (itemProvider?._listId != listProvider.selectedListId && listProvider.selectedListId != null) { itemProvider?.setListIdAndFetch(listProvider.selectedListId!); } return itemProvider!; }, ), ], child: const MyApp(), )
- 商品页面直接监听
ItemProvider数据,刷新逻辑同方案2。
内容的提问来源于stack exchange,提问作者patrick7
相关产品推荐
相关产品推荐

