首先,我想指出一个包可用于StatelessWidget
从函数中生成:functional_widget
增益是性能不一定是真的。这取决于你如何使用你的小部件,主要是你如何使用它们来管理你的状态。
默认情况下,与应用程序中不利用其功能的函数相比,类可能会降低性能。
真正的问题是:他们的力量是什么?
简单:类可以相互独立更新。函数不能
类可以部分更新小部件树。
考虑一个重建每一帧并返回其子级的小部件:
class InfiniteLoop extends StatefulWidget {
const InfiniteLoop({Key key, this.child}) : super(key: key);
final Widget child;
@override
_InfiniteLoopState createState() => _InfiniteLoopState();
}
class _InfiniteLoopState extends State<InfiniteLoop> {
@override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {}));
return widget.child;
}
}
现在,如果我们将整个应用程序包装在那个小部件中,会发生什么?
void main() => runApp(InfiniteLoop(child: MyApp()));
没有什么
当然,您将拥有一个经常在您的树中重建的小部件。但实际上,build
方法MyApp
只会被调用一次。
这是因为 Flutter 能够在小部件的实例没有改变时中止树的重建。
类可以滥用这种优化。
使用类可以巧妙地将小部件树的重建拆分为独立的部分。
列出一个类允许的所有潜在优化因素是不合理的,因为太多了。
以下示例是一个小部件,它采用int
并将其格式化为Text
. 问题是,此小部件仅在int
传递更改时才会重建:
class Counter extends StatelessWidget {
const Counter({Key key, this.value}) : super(key: key);
final int value;
@override
Widget build(BuildContext context) {
return Text(value.toString());
}
@override
bool operator ==(Object other) =>
identical(this, other) || (other is Counter && other.value == value);
@override
int get hashCode => value.hashCode;
}
这是有效的,因为 Flutter 使用==
运算符来了解小部件是否应该更新(因此const
构造函数是一个很好的优化因素)。
这不是唯一的解决方案,但它是函数无法完成的一个很好的例子。