在这种情况下,两个选项在重建小部件和性能方面有什么区别?
小工具类:
class Dummy() extends StatelessWidget {
const Dummy();
@override
Widget build(BuildContext context) {
return const Text(„text“);
}
}
选项1:
class Option1 extends StatelessWidget {
const Option1();
@override
Widget build(BuildContext context) {
return SizedBox(
child: const Dummy(),
);
}
}
选项2:
class Option2 extends StatelessWidget {
const Option2();
Widget createDummyWidget() {
return const Dummy();
}
@override
Widget build(BuildContext context) {
return SizedBox(
child: createDummyWidget(),
);
}
}
将小部件拆分为方法是一种反模式
例如,如果我们有一个看起来像这样的小部件:
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Row(
children: [
Text('Counter: $_counter'),
Container(
child: Column(
children: [
Text('Hello'),
Row(
children: [
Text('there'),
Text('world!'),
],
),
],
),
),
],
);
}
}
如果使用功能窗口小部件
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
Widget _buildNonsenseWidget() {
return Container(
child: Column(
children: [
Text('Hello'),
Row(
children: [
Text('there'),
Text('world!'),
],
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Text('Counter: $_counter'),
// The deeply nesting widget is now refactored into a
// separate method and we have a cleaner build method. Yay!
_buildNonsenseWidget(),
],
);
}
}
那么问题出在哪里呢
每当_counter的值发生变化时,框架就会调用构建方法。这会触发我们的小部件重新构建自己。问题是每次_counter的值更改时都会调用_buildNonsenseWidget((,这最终会一次又一次地重建小部件树。无偿重建在这种情况下,没有理由重建特定的小部件树。
_buildNonsenseWidget((返回的小部件树本质上是无状态的——我们只需要构建一次。遗憾的是,因为小部件树是通过_buildNonsenseWidget((方法构建的,所以Flutter框架每次重建父小部件时都会重建它。
从本质上讲,我们在重建一些不需要重建的东西时浪费了宝贵的CPU周期。之所以会出现这种情况,是因为从框架的角度来看,长时间构建方法和拆分为多个较小方法的构建方法之间没有区别。请注意,这只是一个简单的例子——这对更复杂的应用程序有更大的影响。
拆分长构建方法-重新访问这个解决方案相对简单,尽管它会产生几行额外的代码。我们没有将构建方法拆分为更小的方法,而是将它们拆分为小部件-StatelessWidgets,也就是
当我们重构前面的例子时,我们会得到这样的结果:
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Row(
children: [
Text('Counter: $_counter'),
// The deeply nesting widget is now refactored into a
// stateless const widget. No more needless rebuilding!
const _NonsenseWidget(),
],
);
}
}
class _NonsenseWidget extends StatelessWidget {
const _NonsenseWidget();
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Text('Hello'),
Row(
children: [
Text('there'),
Text('world!'),
],
),
],
),
);
}
}
结论
与其将构建方法拆分为多个较小的方法,不如将它们拆分为StatelessWidgets。通过这种方式,您将不会为了浪费CPU周期而多次重建静态小部件树。当谈到优化Flutter应用程序的性能时,这可能是挂在最下面的果实之一。
我使用了这篇文章:https://iiro.dev/splitting-widgets-to-methods-performance-antipattern/