在这种情况下,两个选项在重建小部件和性能方面有什么区别?
小部件类:
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 的值发生变化时,框架就会调用 build 方法。这会触发我们的小部件重建自身。问题是每次 _counter 的值发生变化时都会调用 _buildNonsenseWidget() - 这最终会一遍又一遍地重建小部件树。 重建毫无意义 在这种情况下,没有理由重建特定的小部件树。
_buildNonsenseWidget() 返回的 widget 树本质上是无状态的 - 我们只需要构建它一次。遗憾的是,由于 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/