如何用Flutter Riverpod按日期差值过滤列表数据
使用Flutter Riverpod实现列表过滤逻辑
1. 定义过滤类型枚举
先创建枚举类标识四种过滤状态:
enum FilterType { all, // 显示全部数据 next, // 剩余天数≥15 almostDone, // 0 < 剩余天数 < 15 done, // 剩余天数≤0 }
2. 创建过滤状态管理Provider
用StateProvider保存当前选中的过滤类型,默认显示全部:
final filterTypeProvider = StateProvider<FilterType>((ref) => FilterType.all);
3. 实现过滤数据Provider
假设你已有原始数据的Provider(比如originalDataProvider)和计算剩余天数的方法,直接实现核心过滤逻辑:
// 示例数据模型(替换成你实际的模型) class Task { final String title; final DateTime targetDate; Task({required this.title, required this.targetDate}); } // 原始数据源Provider(替换成你实际的数据源) final originalDataProvider = Provider<List<Task>>((ref) { return [ Task(title: "任务A", targetDate: DateTime.now().add(const Duration(days: 20))), Task(title: "任务B", targetDate: DateTime.now().add(const Duration(days: 10))), Task(title: "任务C", targetDate: DateTime.now().subtract(const Duration(days: 5))), ]; }); // 复用你已实现的日期差计算方法 int calculateRemainingDays(DateTime targetDate) { final now = DateTime.now(); return targetDate.difference(now).inDays; } // 核心过滤数据Provider final filteredDataProvider = Provider<List<Task>>((ref) { final rawData = ref.watch(originalDataProvider); final currentFilter = ref.watch(filterTypeProvider); switch (currentFilter) { case FilterType.all: return rawData; case FilterType.next: return rawData.where((task) { final remaining = calculateRemainingDays(task.targetDate); return remaining >= 15; }).toList(); case FilterType.almostDone: return rawData.where((task) { final remaining = calculateRemainingDays(task.targetDate); return remaining > 0 && remaining < 15; }).toList(); case FilterType.done: return rawData.where((task) { final remaining = calculateRemainingDays(task.targetDate); return remaining <= 0; }).toList(); } });
4. 在UI中应用过滤逻辑
结合ListView.builder和过滤切换控件实现完整UI:
class FilteredTaskList extends ConsumerWidget { const FilteredTaskList({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final filteredTasks = ref.watch(filteredDataProvider); final currentFilter = ref.watch(filterTypeProvider); return Scaffold( appBar: AppBar( title: const Text("任务列表"), actions: [ DropdownButton<FilterType>( value: currentFilter, items: FilterType.values.map((type) { return DropdownMenuItem( value: type, child: Text(_getFilterText(type)), ); }).toList(), onChanged: (newType) { if (newType != null) { ref.read(filterTypeProvider.notifier).state = newType; } }, ) ], ), body: ListView.builder( itemCount: filteredTasks.length, itemBuilder: (context, index) { final task = filteredTasks[index]; final remainingDays = calculateRemainingDays(task.targetDate); // 复用你已实现的颜色逻辑 final textColor = remainingDays >=15 ? Colors.green : remainingDays >0 ? Colors.orange : Colors.grey; return ListTile( title: Text(task.title, style: TextStyle(color: textColor)), subtitle: Text(remainingDays >0 ? "剩余$remainingDays天" : "已过期"), ); }, ), ); } String _getFilterText(FilterType type) { switch(type) { case FilterType.all: return "全部"; case FilterType.next: return "距截止≥15天"; case FilterType.almostDone: return "距截止1-14天"; case FilterType.done: return "已过期"; } } }
核心逻辑说明
- 过滤逻辑通过Riverpod的依赖追踪自动更新,原始数据或过滤类型变化时,
filteredDataProvider会自动重新计算并刷新UI - 完全复用你已有的日期差计算和颜色设置逻辑,无需额外修改原有业务代码
- 过滤类型切换仅需修改
filterTypeProvider的状态,Riverpod会自动联动更新列表数据
内容的提问来源于stack exchange,提问作者JoseO
相关产品推荐
相关产品推荐

