Flutter Riverpod ref.read() vs ref.listen() vs ref.watch()

Flutter Riverpod ref.read() vs ref.listen() vs ref.watch()

看完了documentation,没有很好的解释什么是ref.read()ref.watch()ref.listen()

我的问题如下:

Riverpod 是 Provider 包的完全重写 我还没有用过 Riverpod 但作为提供者的经验,我将分享一些细节

read()

用于听一次;它可能是函数或变量

watch()

是为了多听时间,即听真话;所以当数据发生变化时将被监听并采用新值

lisen()

watch 和 lisen 之间的主要区别在于,如果侦听的提供程序更改,则不会重建 widget/provider,而是使用 ref.listen 调用自定义函数。

这对于在发生特定更改时执行操作很有用,例如在发生错误时显示快餐栏。

了解更多信息 take a look at this

这些函数的作用和区别是什么?

阅读()

使用 read 获取值 of/in 提供程序一次(one-time 读取)

观看()

第一次使用 watch 获取值 of/in 提供程序,每次值更改时(就像订阅提供程序一样查看它,因此您会在任何时候收到通知一个变化)

听()

listen 类似于 watch。主要区别在于 return 类型。 watch return 直接使用新值,listen return 使用 void 但是可以通过回调访问新值和旧值(参见下面的示例)

我可以在哪些地方使用这些功能?

你可以在 initState 这样的地方使用 read ,像 onPressed 这样的回调等等。 watchlisten 不应该被异步调用,比如里面ElevatedButton 的 onPressed。也不应在 initState 和其他州 life-cycles.

中使用

正如 Kaan Taha Köken 指出的那样:

AVOID using [read] for creating widgets with a value that never changes and CONSIDER using [Provider] or select for filtering unwanted rebuilds.

我什么时候应该使用这些功能?

阅读()

如果您只想提供程序的值一次,请使用 read

观看()

如果您希望始终获取值,请使用 watch

示例:具有 StateProvider

的计数器应用
final counterProvider = StateProvider((ref) => 0);
class HomePage extends ConsumerWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counter = ref.watch(counterProvider);
    ref.listen(
      counterProvider,
      (previous, next) {
        print("The new value is $next");
        if (next == 5) {
          print("I just reached 5");
        }
      },
    );
    return Scaffold(
      body: Center(
        child: Text(
          counter.toString(),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          ref.read(counterProvider.state).state += 1;
        },
      ),
    );
  }
}

上面的示例显示了 watchreadlisten 的用法。

  • 我们正在 watch 计算 counter 值,因此只要有变化,它就会在 UI 中更新。
  • 我们 listen 正在 counter 打印更新后的值并在 I've reached 5 为 5 时打印。
  • 为了增加值,我们 read 提供者状态并在按下 FloatingActionButton 时添加 1