[英]Flutter Riverpod context.read vs Provider in the build method
[英]Triggering Widget Rebuilds with Provider's context.read<T>() Method
根据 Flutter 的文档和本示例,据我了解,Provider 包的context.read<T>
和context.watch<T>
方法之间的主要区别与触发小部件重建有关。 您可以在任何小部件的build
方法中调用context.watch<T>()
来访问当前状态,并在状态发生变化时要求 Flutter 重建您的小部件。 您不能在构建方法之外使用context.watch<T>()
,因为这通常会导致细微的错误。 相反,他们说,使用context.read<T>()
,它获取当前状态但不要求 Flutter 进行未来的重建。
我尝试制作这个简单的应用程序:
class MyDataNotifier extends ChangeNotifier {
String _testString = 'test';
// getter
String get testString => _testString;
// update
void updateString(String aString) {
_testString = aString;
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => MyDataNotifier(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(context.read<MyDataNotifier>().testString),
),
body: Container(
child: Level1(),
),
),
);
}
}
class Level1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
onChanged: (val) {
context.read<MyDataNotifier>().updateString(val);
},
),
Text(context.read<MyDataNotifier>().testString),
],
);
}
}
所有的调用都是对counter.read<T>()
。 应用程序的状态会发生变化,但不会使用新值重建 UI。 我必须更改对counter.watch<T>()
的调用之一才能重建状态。
另一方面,在DZone 的简单示例中,UI 重建,并且所有调用都是对 context.read() 的。
他们的代码和我的有什么不同? 为什么我不能用 counter.read() 调用重建?
TLDR:快速浏览一下,DZone 文章似乎有一个错误。
context.watch<Foo>()
做了两件事:
context
标记为依赖于Foo
context.read<Foo>()
只做 1)。
每当您的 UI 依赖于Foo
,您都应该使用context.watch
,因为这会适当地通知 Flutter 该依赖项,并且它将被正确重建。
一般来说,它归结为这个经验法则:
build()
方法或任何其他返回Widget
方法中使用context.watch
onPressed
处理程序(和其他相关函数)中使用context.read
人们似乎不恰当地使用context.read
主要原因是出于性能原因。 一般来说,为了性能,更喜欢context.read
不是context.watch
是一种反模式。 相反,如果您想限制小部件重建的频率,您应该使用context.select
。 每当您有一个经常更改的值时,这是最有用的。
假设您有以下状态:
class FooState extends ChangeNotifier {
// imagine this us updated very often
int millisecondsSinceLastTap;
// updated less often
bool someOtherProperty = false;
}
如果您有一个显示someOtherProperty
的小部件,则context.watch
可能会导致许多不必要的重建。 相反,您可以使用context.select
仅取决于状态的已处理部分:
// read the property, rebuild only when someOtherProperty changes
final property = context.select((FooState foo) => foo.someOtherProperty);
return Text('someOtherProperty: $property');
即使经常更新值,如果提供给 select 的函数的输出没有改变,小部件也不会重建:
// even though millisecondsSinceLastTap may be updating often,
// this will only rebuild when millisecondsSinceLastTap > 1000 changes
final value = context.select((FooState state) => state.millisecondsSinceLastTap > 1000);
return Text('${value ? "more" : "less"} than 1 second...');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.