假设我想通过使用initialValue:
上的TextFormField
属性来初始化文本字段,并且我需要我的初始值来自提供者。我在docs上读到,从build方法内部调用read()
被认为是不好的做法,但是从处理程序中调用是可以的(例如onPressed
)。因此,我想知道是否可以从initialValue
属性中进行读取,如下所示吗?
答案 0 :(得分:2)
否,如果您使用钩子,则应使用useProvider
,否则请使用ConsumerWidget
/ Consumer
。
区别在于,initialValue
字段是构建方法的一部分,就像您所说的,onPressed
是构建方法之外的处理程序。
提供商的核心方面是,随着提供的价值的变化,优化重建。在构建方法中使用context.read
会使此好处无效,因为您没有在听提供的值。
在匿名函数(context.read
,onChanged
,onPressed
等)中,强烈建议使用onTap
,因为这些函数会在以下位置检索提供的值:该函数执行的时间。这意味着该函数将始终使用该提供程序的当前值执行,而不必侦听该提供程序。用于读取提供程序的其他方法使用侦听器,对于匿名函数,侦听器更昂贵且不必要。
在您的示例中,您想要设置initialValue
中的TextFormField
。以下是如何使用hooks_riverpod和flutter_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
仅会重建其子项,因为只有它们依赖提供的数据。