Flutter Riverpod-在内部build方法中使用read()

时间:2020-10-07 22:25:45

标签: flutter flutter-provider

假设我想通过使用initialValue:上的TextFormField属性来初始化文本字段,并且我需要我的初始值来自提供者。我在docs上读到,从build方法内部调用read()被认为是不好的做法,但是从处理程序中调用是可以的(例如onPressed)。因此,我想知道是否可以从initialValue属性中进行读取,如下所示吗?

enter image description here

1 个答案:

答案 0 :(得分:2)

否,如果您使用钩子,则应使用useProvider,否则请使用ConsumerWidget / Consumer

区别在于,initialValue字段是构建方法的一部分,就像您所说的,onPressed是构建方法之外的处理程序。

提供商的核心方面是,随着提供的价值的变化,优化重建。在构建方法中使用context.read会使此好处无效,因为您没有在听提供的值。

在匿名函数(context.readonChangedonPressed等)中,强烈建议使用onTap,因为这些函数会在以下位置检索提供的值:该函数执行的时间。这意味着该函数将始终使用该提供程序的当前值执行,而不必侦听该提供程序。用于读取提供程序的其他方法使用侦听器,对于匿名函数,侦听器更昂贵且不必要。

在您的示例中,您想要设置initialValue中的TextFormField。以下是如何使用hooks_riverpodflutter_hooks完成此操作的方法。

class HooksExample extends HookWidget {
  const HooksExample({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      initialValue: useProvider(loginStateProv).email,
    );
  }
}

对于不喜欢使用钩子的读者:

class ConsumerWidgetExample extends ConsumerWidget {
  const ConsumerWidgetExample({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    return TextFormField(
      initialValue: watch(loginStateProv).email,
    );
  }
}

或者:

class ConsumerExample extends StatelessWidget {
  const ConsumerExample({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, watch, child) {
        return TextFormField(
          initialValue: watch(loginStateProv).email,
        );
      },
    );
  }
}

主要区别在于Consumer仅会重建其子项,因为只有它们依赖提供的数据。