[英]StatelessWidget vs a function returning Widgets in terms of performance
Is there any difference, performance wise, in using a StatelessWidget
vs a function returning a Widget
?在性能方面,使用StatelessWidget
与function returning a Widget
有什么区别吗?
I'm well aware of at least the differences pointed out in this flutter's repo issue which don't have a relationship with performance.我很清楚至少在这个颤振的回购问题中指出的差异与性能没有关系。
The fact is that I have some colleagues claiming that functional widgets
are worst in terms of performance but after reading a little bit about the subject I cannot find any conclusive piece of documentation that can give credit to that assertion so any kind of clarification regarding this matter will be very welcome!事实是,我有一些同事声称functional widgets
在性能方面最差,但是在阅读了一些关于该主题的内容后,我找不到任何可以证明该断言的结论性文档,因此对此问题进行任何形式的澄清会很受欢迎!
As far as I can see the only difference between them would be in the case of using a const Widget
, which seems that would avoid the rebuilding phase.据我所知,它们之间的唯一区别在于使用const Widget
的情况,这似乎可以避免重建阶段。
First of all, I'd like to note that a package is available to make a StatelessWidget
from a function: functional_widget首先,我想指出一个包可用于从函数中创建StatelessWidget
: functional_widget
The gain is performance is not necessarily true.增益是性能不一定是真的。 It depends on how you use your widgets, mostly how you use them to manage your state.这取决于你如何使用你的小部件,主要是你如何使用它们来管理你的状态。
By default, classes may degrade performances when opposed to functions in an application that doesn't utilize their power.默认情况下,与应用程序中不利用其功能的函数相比,类可能会降低性能。
The real question is: What is their power?真正的问题是:他们的力量是什么?
Simple: Classes can update independently from each other.简单:类可以相互独立更新。 Functions cannot函数不能
It is possible for classes to partially update the widget tree.类可以部分更新小部件树。
Consider a widget that rebuilds every frame and returns its child:考虑一个重建每一帧并返回其子级的小部件:
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;
}
}
Now if we wrap our whole application in that widget, what happens?现在,如果我们将整个应用程序包装在那个小部件中,会发生什么?
void main() => runApp(InfiniteLoop(child: MyApp()));
Nothing没有什么
Sure, you'll have one widget that rebuilds often in your tree.当然,您将拥有一个经常在您的树中重建的小部件。 But in reality, the build
method of MyApp
will be called only once.但实际上, MyApp
的build
方法只会被调用一次。
That's because Flutter is able to abort the tree rebuild when the instance of a widget doesn't change.这是因为 Flutter 能够在小部件的实例没有改变时中止树的重建。
Classes can abuse of this optimization.类可以滥用这种优化。
Using classes it is possible to cleverly split the rebuilding of your widget tree into independent parts.使用类可以巧妙地将小部件树的重建拆分为独立的部分。
It's not reasonable to list all the potential optimization factors that a class allow, as there are too many.列出一个类允许的所有潜在优化因素是不合理的,因为太多了。
The following example is a widget that takes an int
and formats it into a Text
.以下示例是一个小部件,它采用int
并将其格式化为Text
。 The catch is, this widget will rebuild only if the int
passed change:问题是,只有当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;
}
This works because Flutter uses the ==
operator to know if a widget should update or not (hence why const
constructor is a good optimization factor).这是有效的,因为 Flutter 使用==
运算符来了解小部件是否应该更新(因此为什么const
构造函数是一个很好的优化因素)。
This is not the only solution, but it's a good example of something that functions can't do.这不是唯一的解决方案,但它是函数无法完成的一个很好的例子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.