一尘不染

在initState或类构造函数中定义小部件,而不是在构建?

flutter

我看到的大多数示例和流行的智慧都为类中的Widget使用了一个典型的模板,该类中的所有其他Widget都在该build方法中创建(我认为这可以使代码更清晰,但请放开它)。

但是,如果所引用的窗口小部件不做进一步更改,则每个构建调用仍将重新创建该窗口小部件。在an
initState或class构造函数中分配它并在以后引用它时,是否存在任何实际问题?

琐碎的例子

// this partial from inside the build() method currently
Container(
  padding: const EdgeInsets.only(bottom: 8.0),
    child: Text(
      'Oeschinen Lake Campground',
       style: TextStyle(
       fontWeight: FontWeight.bold,
    ),
  ),
 ),

// Now inside initState or class Constructor
myText = Text(
      'Oeschinen Lake Campground',
       style: TextStyle(
       fontWeight: FontWeight.bold,
    ),
 );

...
// Still inside build method (in fact this could also go inside the constructor ?)
Container( 
  padding: const EdgeInsets.only(bottom: 8.0),
  child: myText
)

这仅适用于不基于状态引用的代码。

以这种方式,除了设计/美学之外,还有其他缺点吗?尽管这个示例很简单,但我一直认为,当应用变得更加复杂时,也许不必重新构建非基于状态的小部件可能会有一些性能/电池/顶空的好处(我也意识到我认为小部件会更进一步每次树都可能仍然需要一个新对象)。但是,我是扑扑/飞镖的新手,所以要警惕一些我没有适当考虑的问题,或者从根本上误解了某些方面。


阅读 270

收藏
2020-08-13

共1个答案

一尘不染

这是合法的优化。实际上,您甚至可以对与状态相关的小部件(与结合使用didUpdateWidget)执行相同的操作。胜利是微不足道的。

小部件非常轻巧,Dart已针对许多微实例进行了优化。

这种方法有一个问题:您松开热装。


重用旧的窗口小部件实例仍然非常有用。仿佛小部件实例不变,Flutter中止了子树的构建。

这在动画中经常使用,而 不是
每帧都重建整个窗口小部件树。一个典型的例子是AnimatedBuilder(但全部XXTransition遵循相同的逻辑)

Animation animation;

AnimatedBuilder(
  animation: animation,
  child: Text('Foo'),
  builder: (context, child) {
    return Align(
      alignment: Alignment(.5, animation.value),
      child: child,
    );
  },
);

在这里,这会自愿重用child实例,以免Text再次调用build方法。


那么,我应该这样做吗?

好,是的,不是。优化您的应用程序总是很酷的。但是除了使用变量之外,还有一种更好的方法:const构造函数。

要重用您的示例,您可以将“总是相同的”小部件树提取到带有const构造函数的自定义小部件中:

class _Foo extends StatelessWidget {
  const _Foo({Key key}): super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(
      'Oeschinen Lake Campground',
      style: TextStyle(
        fontWeight: FontWeight.bold,
      ),
    );
  }
}

然后在您的build方法中以这种方式使用它:

@override
Widget build(BuildContext context) {
  return Container(
    padding: const EdgeInsets.only(bottom: 8.0),
    child: const _Foo(),
  );
}

这样,您可以获得缓存小部件实例的好处。但是您不要松开热装。

完美吧?

2020-08-13