将小部件拆分为方法是一种反模式
因此,举例来说,如果我们有一个看起来像这样的小部件:
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 的值发生变化时,框架就会调用 build 方法。这会触发我们的小部件重建自身。问题是每次 _counter 的值发生变化时都会调用 _buildNonsenseWidget() - 这最终会一遍又一遍地重建小部件树。
重建毫无意义
在这种情况下,没有理由重建特定的小部件树。
_buildNonsenseWidget() 返回的小部件树本质上是无状态的 - 我们只需要构建它一次。遗憾的是,由于 widget 树是通过 _buildNonsenseWidget() 方法构建的,因此每次父 widget 重建时,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!'),
],
),
],
),
);
}
}
结论
不要将构建方法拆分为多个较小的方法,而是将它们拆分为 StatelessWidget。这样,您就不会多次重建静态部件树,而只会浪费 CPU 周期。当谈到优化 Flutter 应用程序的性能时,这可能是最容易实现的目标之一。
我用了这篇文章:https://iiro.dev/splitting-widgets-to-methods-performance-antipattern/