在initState或类构造函数中定义小部件,而不是在构建? [英] Defining widgets inside initState or class constructors rather than build?

查看:81
本文介绍了在initState或类构造函数中定义小部件,而不是在构建?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Most of the examples and prevailing wisdom I see use a typical template for a Widget within a class, where ALL further widgets are created within the build method (which I think can give a clarity of code, but setting this aside).

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

However, if the referenced widget is not going to change further, it still gets recreated every build call. Is there any actual issue with assigning this in an initState or the class constructor and referencing it later ?

私有化示例

// 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
)

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

This is just for code that isn't based on a state reference.

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

Are there any downsides other than design/aesthetics to doing it this way ? Whilst this example is trivial, I keep thinking that maybe there are some performance/battery/headspace benefits to not keep having to rebuild non state based widgets when the app gets a lot more complex (I'm also aware I think that a Widget further up the tree may still call for a new object each time). However, I'm new to flutter/dart, so wary about some issues I haven't considered properly, or fundamentally misunderstood some aspects.

推荐答案

这是合法的优化.实际上,您甚至可以对状态依赖的小部件(与didUpdateWidget组合)进行相同的操作. 不过胜利微不足道.

This is a legitimate optimization. In fact you can even do the same with state dependent widgets (combined with didUpdateWidget). The win is negligible though.

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

Widgets are extremely light, and Dart is optimized for a lot of micro instantiations.

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

And there's one problem wih this approach: you loose hot-reload.

重用旧的窗口小部件实例仍然非常有用.仿佛小部件实例没有变化,Flutter放弃了子树的构建.

Reusing old widget instances is still pretty useful. As if the widget instance don't change, Flutter abort the subtree build.

动画中经常使用它来每帧重建整个窗口小部件树.一个典型的例子是AnimatedBuilder(但所有XXTransition都遵循相同的逻辑)

This is used very often in animations to not rebuild the entire widget tree every frames. A typical example would be AnimatedBuilder (but all XXTransition follow the same logic)

Animation animation;

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

在这里,这会自愿重用child实例,这样就不会再次调用Text生成方法.

Here, this voluntarily reuse the child instance so that Text build method doesn't get called again.

那么,我应该这样做吗?

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

Well, yes and no. It is always cool to optimize your application. But instead of doing it using variables there's a better way : const constructors.

要重用您的示例,您可以使用const构造函数将始终相同"的小部件树提取到自定义小部件中:

To reuse your example, you could extract your "always the same" widget tree into a custom widget with a const constructor:

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方法中以这种方式使用它:

and then use it this way inside your build method:

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

这样,您可以获得缓存小部件实例的好处.但是您不会丢失热装弹.

This way you get the benefits of caching the widget instance. BUT you don't loose hot reload.

完全正确吗?

这篇关于在initState或类构造函数中定义小部件,而不是在构建?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆