由于各种原因,有时会再次调用我的小部件的 build
方法 .
我知道这是因为父母更新了 . 但这会导致不良影响 . 导致问题的典型情况是以这种方式使用 FutureBuilder
:
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: httpCall(),
builder: (context, snapshot) {
// create some layout here
},
);
}
在此示例中,如果再次调用构建方法,则会触发另一个http请求 . 这是不受欢迎的 .
考虑到这一点,如何处理不需要的构建?有什么方法可以阻止构建调用?
1 回答
构建方法的设计应该是纯粹的/没有副作用的 . 这是因为许多外部因素可以触发新的小部件构建,例如:
路由弹出/推送,用于输入/输出动画
屏幕调整大小,通常是由于键盘外观或方向更改
父窗口小部件重新创建其子窗口
小部件依赖于(
Class.of(context)
模式)更改的InheritedWidgetThis means that the build method should not trigger an http call or modify any state .
这与问题有什么关系?
你面临的问题是你的构建方法有副作用/不纯,造成无关的构建调用麻烦 .
您应该使构建方法保持纯粹,而不是阻止构建调用,以便可以随时调用它而不会产生影响 .
对于您的示例,您将窗口小部件转换为
StatefulWidget
然后将该HTTP调用解压缩到State
的initState
:当小部件的实例保持不变时;有目的地颤动不会重建孩子 . 这意味着您可以缓存窗口小部件树的部分以防止不必要的重建 .
最简单的方法是使用dart
const
构造函数:感谢
const
关键字,即使构建被调用数百次,DecoratedBox
的实例也将保持不变 .但您可以手动获得相同的结果:
在此示例中,当StreamBuilder收到新值的通知时,即使StreamBuilder / Column执行,也不会重建
subtree
. 这是因为由于闭包,MyWidget
的实例没有改变 .这种模式在动画中经常使用 . 典型用户是
AnimatedBuilder
和所有*转换,例如AlignTransition
.你也可以将
subtree
存储到你的类的一个字段中,尽管不太推荐,因为它会破坏热重载 .