为什么不能在build()中使用context.read,但是可以将Provider.of与listen:false一起使用? [英] Why can't I use context.read in build(), but I can use Provider.of with listen: false?
问题描述
文档中指出它们是相同的,并且 context.read
只是 Provider.of< x>(context)的快捷方式,请听:假)
。
如果我尝试在构建方法中使用 context.read
,则控制台中也会出现错误,但是并没有解释原因。
It's stated in the docs that these are the same, and context.read
is just a shortcut for Provider.of<x>(context, listen: false)
.
There's also an error in the console if I try to use context.read
in a build method, but it doesn't explain the reason.
我也找到了这个主题:是Provider.of(context,listen:false)是否等同于context.read()?
但它没有回答为什么。
I also found this topic: Is Provider.of(context, listen: false) equivalent to context.read()? But it doesn't answer "why".
推荐答案
-
context.read
不允许在build
,因为在那使用它非常危险,并且有更好的解决方案。context.read
is not allowed insidebuild
because it is very dangerous to use there, and there are much better solutions available.Provider.of
在build
中允许向后兼容。Provider.of
is allowed inbuild
for backward-compatibility.总体而言,
context.read
背后的原因是build 内不允许的内容noreferrer>其文档:Overall, the reasoning behind why
context.read
is not allowed insidebuild
is explained in its documentation:
不要在构建过程中调用[read],如果值仅用于事件:
DON'T call [read] inside build if the value is used only for events:
Widget build(BuildContext context) { // counter is used only for the onPressed of RaisedButton final counter = context.read<Counter>(); return RaisedButton( onPressed: () => counter.increment(), ); }
虽然此代码本身并未出错,但这是一种反模式。
重构小部件
以将计数器
用于其他用途后,将来很容易导致错误,但是忘记将[read]更改为[While this code is not bugged in itself, this is an anti-pattern. It could easily lead to bugs in the future after refactoring the widget to use
counter
for other things, but forget to change [read] into [watch].考虑在事件处理程序内部调用[read]:
CONSIDER calling [read] inside event handlers:
Widget build(BuildContext context) { return RaisedButton( onPressed: () { // as performant as the previous previous solution, but resilient to refactoring context.read<Counter>().increment(), }, ); }
这与先前的反模式具有相同的效率,但没有b $ b具有易碎的缺点。
This has the same efficiency as the previous anti-pattern, but does not suffer from the drawback of being brittle.
请勿使用[read]创建值永远不变的小部件
DON'T use [read] for creating widgets with a value that never changes
Widget build(BuildContext context) { // using read because we only use a value that never changes. final model = context.read<Model>(); return Text('${model.valueThatNeverChanges}'); }
$$$$ b好的,这不应该用[read]完成。
依靠[read]进行优化非常脆弱,并且
依赖于实现细节。While the idea of not rebuilding the widget if something else changes is good, this should not be done with [read]. Relying on [read] for optimisations is very brittle and dependent on an implementation detail.
考虑因素使用[选择]来过滤不需要的重建
CONSIDER using [select] for filtering unwanted rebuilds
Widget build(BuildContext context) { // Using select to listen only to the value that used final valueThatNeverChanges = context.select((Model model) => model.valueThatNeverChanges); return Text('$valueThatNeverChanges'); }
虽然比[read]更为详细,但使用[select]更安全。
它不依赖Model
上的实现细节,并且使
不可能有我们的UI无法刷新的错误。While more verbose than [read], using [select] is a lot safer. It does not rely on implementation details on
Model
, and it makes impossible to have a bug where our UI does not refresh.这篇关于为什么不能在build()中使用context.read,但是可以将Provider.of与listen:false一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!