You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Riverpod监听Provider状态变更后销毁,列表过滤失效求助

问题排查与修复方案

核心问题根源

  1. FutureProvider依赖监听失效:recordListFiltered中先await异步Provider,后续的ref.watch(etiquetaSelecProvider)无法被Riverpod正确追踪依赖,导致标签变更时Provider不仅不重新计算,反而被销毁。
  2. 过滤逻辑类型不匹配:用Etiqueta的Set判断是否包含Records对象,条件永远为true,过滤完全无效。
  3. UI与Provider状态不同步:ChipEtiqueta本地维护filters状态,未从Provider读取真实选中状态,导致UI显示与实际过滤条件不一致。
  4. Etiqueta对象相等性判断缺失:Set的contains依赖==和hashCode方法,若未重写则无法正确识别相同标签。

分步修复方案

1. 修正recordListFiltered Provider的依赖监听与过滤逻辑

调整代码顺序,确保同步依赖优先被监听,同时修正过滤条件(假设Records对象包含etiquetas属性存储关联标签):

@Riverpod(keepAlive: true)
FutureOr<List<Records>> recordListFiltered(RecordListFilteredRef ref) async {
  // 先监听同步依赖,再处理异步订单列表
  final selectedEtiquetas = ref.watch(etiquetaSelecProvider);
  final recordsList = await ref.watch(cajaControllerProvider.future);

  print('当前选中标签: $selectedEtiquetas');

  // 过滤逻辑:排除包含任意选中标签的订单(可根据需求调整)
  final updatedList = recordsList.where((record) {
    if (selectedEtiquetas.isEmpty) return true; // 无选中标签时返回全部订单
    return !record.etiquetas.any((etiqueta) => selectedEtiquetas.contains(etiqueta));
  }).toList();

  return updatedList;
}

2. 修复ChipEtiqueta的状态同步问题

移除本地filters状态,直接从Provider读取选中状态,确保UI与数据源完全同步:

// 改为ConsumerWidget,无需本地状态
class ChipEtiqueta extends ConsumerWidget {
  final Etiqueta etiqueta;
  final bool isFilter;
  final VoidCallback? funct;

  const ChipEtiqueta({
    required this.etiqueta,
    this.isFilter = false,
    this.funct,
    super.key,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 直接从Provider获取选中标签集合
    final selectedEtiquetas = ref.watch(etiquetaSelecProvider);
    final selecEtiquetasProv = ref.read(etiquetaSelecProvider.notifier);

    return isFilter
        ? FilterChip(
            label: Text(
              etiqueta.nombre,
              style: Theme.of(context)
                  .textTheme
                  .labelSmall!
                  .copyWith(fontSize: 10.fSize, fontWeight: FontWeight.w600),
            ),
            // 用Provider状态判断选中状态
            selected: selectedEtiquetas.contains(etiqueta),
            onSelected: (bool selected) {
              if (selected) {
                selecEtiquetasProv.addEtiquetaSelec(etiqueta);
              } else {
                selecEtiquetasProv.deleteEtiquetaSelec(etiqueta);
              }
            },
            shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(50))),
            padding: const EdgeInsets.symmetric(vertical: -7, horizontal: 0),
            labelPadding:
                const EdgeInsets.symmetric(horizontal: 5, vertical: -3),
          )
        : Chip(
            label: Text(
              etiqueta.nombre,
              style: Theme.of(context)
                  .textTheme
                  .labelSmall!
                  .copyWith(fontSize: 10.fSize, fontWeight: FontWeight.w600),
            ),
            shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(50))),
            padding: const EdgeInsets.symmetric(vertical: -7, horizontal: 0),
            labelPadding:
                const EdgeInsets.symmetric(horizontal: 5, vertical: -3),
          );
  }
}

3. 给Etiqueta模型添加相等性判断

在etiquetas_model.dart中重写==和hashCode方法,确保Set能正确识别相同标签:

class Etiqueta {
  final String nombre;
  // 若有唯一ID属性,建议用ID判断相等性

  Etiqueta({required this.nombre});

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Etiqueta &&
          runtimeType == other.runtimeType &&
          nombre == other.nombre;

  @override
  int get hashCode => nombre.hashCode;
}

4. 优化标签删除方法(可选)

简化删除逻辑,确保状态更新符合Riverpod要求:

void deleteEtiquetaSelec(Etiqueta etiqueta) {
  state = state.where((e) => e.nombre != etiqueta.nombre).toSet();
}

验证要点

  • 点击标签时,检查控制台输出确认etiquetaSelecProvider状态是否正确更新
  • 观察recordListFiltered是否在标签变更时重新计算并返回过滤后的列表
  • 确认Chip的选中状态与Provider中的状态完全一致

内容的提问来源于stack exchange,提问作者Nicolas Sicard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 19:20:57