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

如何使用Riverpod让ProgressNotifier监听BatchSizeNotifier变更并自重置?

问题描述

当BatchSizeNotifier的状态发生变更时,希望ProgressNotifier通过监听前者的变化自行执行重置操作,但当前实现无法生效。如何使用Riverpod让Provider正确响应其他Provider的变化?

现有代码
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:zero_loss_compress/convertion_stats.dart';

final batchSizeProvider = NotifierProvider<BatchSizeNotifier, int>(() {
  return BatchSizeNotifier();
});

final progressProvider = NotifierProvider<ProgressNotifier, int>(() {
  return ProgressNotifier();
});

class BatchSizeNotifier extends Notifier<int> {
  @override
  int build() {
    return 0;
  }

  void setBatchSizeAndResetConversionState(
    int batchSize,
    WidgetRef ref,
  ) {
    state = batchSize;
    // 希望移除这个调用,让ProgressNotifier自行监听重置
    // ref.read(progressProvider.notifier).reset();
    ref.read(convertionStatsStateProvider.notifier).state =
        ConvertionStats(0, 0);
  }
}

class ProgressNotifier extends Notifier<int> {
  @override
  int build() {
    ref.listen(batchSizeProvider, (previous, next) {
      reset();
    });
    return 0;
  }

  void increment() {
    state = state + 1;
  }

  void reset() {
    state = 0;
  }
}
解决方案

当前写法失效的核心原因:ProgressNotifier的build方法只有在progressProvider被UI或其他Provider订阅时才会执行,否则其中的ref.listen不会注册监听。同时,即使注册了监听,初始构建时也可能误触发重置。可以通过以下两种方式修复:

方式一:通过ref.watch建立依赖,自动重置

在ProgressNotifier的build方法中读取batchSizeProvider,让progressProvider直接依赖前者的状态。当batchSize变化时,build会重新执行,直接返回初始值实现重置:

class ProgressNotifier extends Notifier<int> {
  @override
  int build() {
    // 建立对batchSizeProvider的依赖,状态变化时触发build重执行
    ref.watch(batchSizeProvider);
    // 每次batchSize变更,重置进度为0
    return 0;
  }

  void increment() {
    state = state + 1;
  }

  void reset() {
    state = 0;
  }
}

方式二:用ref.listen精细控制重置时机

如果需要区分初始构建和后续状态变更(比如初始时不执行重置),可以保留ref.listen并添加判断逻辑:

class ProgressNotifier extends Notifier<int> {
  @override
  int build() {
    ref.listen(batchSizeProvider, (previous, next) {
      // 只有当batchSize从已有值变更时,才执行重置
      if (previous != null) {
        reset();
      }
    });
    return 0;
  }

  void increment() {
    state = state + 1;
  }

  void reset() {
    state = 0;
  }
}

额外注意事项

  • 确保BatchSizeNotifier中state = batchSize的更新逻辑正确,Riverpod会自动过滤相同值的状态更新,只有当新值与当前state不同时,才会触发依赖通知。
  • 如果progressProvider从未被任何地方订阅,上述两种方式都不会生效。需要确保UI或其他Provider中使用了ref.watch(progressProvider)或类似方法订阅它。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:04:52