使用FutureProvider时监听数据变化重建ListView.builder实现SQFlite搜索
核心问题
你当前的方案无法触发UI更新的根本原因是:FutureProvider的create方法仅在Provider初始化时执行一次,后续你调用搜索接口获取到的新数据没有和Provider持有的状态绑定,也没有对应的机制通知UI重建。
推荐解决方案
这种需要主动触发数据刷新、支持搜索切换的场景,更适合用ChangeNotifierProvider替代FutureProvider,实现步骤如下:
1. 新增状态管理类
创建可通知状态变化的BillingDataNotifier,统一管理列表数据、加载状态和数据操作方法:
import 'package:flutter/foundation.dart'; class BillingDataNotifier extends ChangeNotifier { List<BillingData>? billingList; bool isLoading = false; final BillingDataService _service = BillingDataService(); // 加载全量账单数据 Future<void> loadFullBillingData() async { isLoading = true; notifyListeners(); billingList = await _service.getBillingData(); isLoading = false; notifyListeners(); } // 执行搜索并更新列表 Future<void> searchConcessionaire(String keyword) async { isLoading = true; notifyListeners(); billingList = await _service.searchConcessionaire(keyword); isLoading = false; notifyListeners(); } }
2. 修改Provider注册逻辑
替换main.dart中的FutureProvider为ChangeNotifierProvider,初始化时自动加载全量数据:
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider( create: (context) => BillingDataNotifier()..loadFullBillingData(), ), ], child: MaterialApp(), ); } }
3. 修改列表页逻辑
在页面中消费BillingDataNotifier,搜索触发时调用对应的搜索方法即可自动刷新UI:
Widget build(BuildContext context) { final billingNotifier = context.watch<BillingDataNotifier>(); return Scaffold( appBar: AppBar( // 搜索框示例,可根据需求替换为你的搜索触发逻辑 title: TextField( onSubmitted: (value) { if (value.trim().isNotEmpty) { billingNotifier.searchConcessionaire(value.trim()); } else { // 搜索词为空时恢复全量数据 billingNotifier.loadFullBillingData(); } }, decoration: const InputDecoration(hintText: "搜索 concessions"), ), ), body: billingNotifier.isLoading || billingNotifier.billingList == null ? const Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: billingNotifier.billingList!.length, itemBuilder: (context, index) { final currentData = billingNotifier.billingList![index]; return ConcessionaireCard( index: index, fullName: currentData.fullName, ctName: currentData.ctName, mtrNo: currentData.mtrNo, prevReading: currentData.prevReading, curReading: currentData.curReading, ); }), ); }
如果你坚持使用FutureProvider的补充方案
如果不想更换Provider类型,可额外注册一个StateProvider存储搜索关键词,让FutureProvider依赖该关键词,每次关键词变更时自动重新执行Future拉取数据:
// 注册两个Provider MultiProvider( providers: [ StateProvider<String?>((ref) => null), // 存储搜索关键词 FutureProvider<List<BillingData>>( create: (context) async { final keyword = context.watch<String?>(); final service = BillingDataService(); if(keyword == null || keyword.isEmpty) { return service.getBillingData(); } return service.searchConcessionaire(keyword); }, ), ], child: MaterialApp(), )
搜索触发时更新StateProvider存储的关键词即可触发FutureProvider重新拉取数据、刷新UI。该方案适合简单场景,灵活度低于ChangeNotifier方案。
内容的提问来源于stack exchange,提问作者Valle John Teruel
相关产品推荐
相关产品推荐

