StatefulWidget和StatelessWidget的性能波动

时间:2019-12-12 17:15:21

标签: flutter dart stateful

当我必须创建在应用程序中多次使用的窗口小部件的“模板”时,我会使用很多StatelessWidgets,因为文档是这样说的:

  

无状态窗口小部件在用户界面的一部分   所描述的不依赖于   对象本身和BuildContext中的配置信息   小部件膨胀了。

这里是一个例子:

class StepInputButton extends StatelessWidget {

  final int pos;
  final String value;

  const StepInputButton({
    this.pos,
    this.value
  });

  @override
  Widget build(BuildContext context) {
    return Row(
      // Text, Icon and a tiny button
    );
  }

}

上面的方法很好,因为我可以在带有CONST的代码中使用const StepInputButton(val, "val"),,从而提高性能。


问题

我正在使用著名的Provider小部件来管理状态,我的应用程序页面通常如下所示:

class SuccessPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    var prov = Provider.of<Type>(context);    
    return Scaffold(...); 
  }

}

这是我的带有脚手架的应用程序页面,其中包含一个抽屉,一个浮动操作按钮和一个appTitle。 在这里,我使用一个StatelessWidget,因为提供程序会为我完成所有工作,因此我不使用setState()。但是他们仍然在官方的flutter文档中说:

  

对于可以动态变化的成分,例如由于有   内部时钟驱动状态,或取决于某些系统状态,   考虑使用StatefulWidget。

所以我必须将class SuccessPage extends StatelessWidget更改为class SuccessPage extends StatefulWidget吗?我有优势吗?

注意:如果您想用另一种方式提出这个问题:我应该使用StatefulWidgets创建状态将要更改的“应用页面”,还是使用StatelessWidgets创建状态不会改变的“可重用窗口小部件”,改变吗?

3 个答案:

答案 0 :(得分:4)

StatefulWidget对于小部件本身保持其自身状态是必需的。在您给出的示例中,Provider包正在为您处理状态,假设您在小部件树的上方使用了正确的提供程序类型(例如ChangeNotifierProvider)。这段代码中似乎也没有任何东西可以从访问小部件的生命周期中受益,因此您不需要访问诸如initStatedispose之类的方法。

这样,窗口小部件本身不需要管理,因此无需将类转换为有状态。

不过,我可能建议的一件事是使用Consumer而不是直接调用Provider.ofConsumer为您处理呼叫,并消除了在Provider检测到状态更改时是否会更新您的小部件的任何歧义。

答案 1 :(得分:3)

您将StatelessWidget用于不会更改其状态的小部件,这些小部件将始终保持不变。例如,appBar是无状态的。build(...)的{​​{1}}函数仅被调用一次,并且在任何StatelessWidgetVariable(s)或{{ 1}}可以再次调用它。

因此,当您需要更改状态(ex值)然后使用Value(s)时,基本上Event(s)用于构建静态的UI小部件

答案 2 :(得分:3)

保持简单:

  1. 如果您的小部件中有 final 个全局变量,则您需要一个StatefulWidget
  2. 如果所有全局变量均为 final ,则应使用StatelessWidget;

原因:

  1. 如果您的全局变量不是最终变量,则意味着可以更改它,并且如果更改了它的值,则意味着您的对象(小部件)的状态也已更改(我正在谈论的基本oops概念)。在这种情况下,您想调用窗口小部件的build方法,以便将更改应用到UI(如果它对您的UI很重要)。我们通过调用setState();来做到这一点,因此在这种用例中使用StatefulWidget
  2. 如果在构造函数中初始化全局变量后就足够了,以后就不需要分配任何值,那么在这种情况下,请使用StatelessWidget

我试图使其保持非常简单且不够技术性,因此,如果您仍然有任何疑问,请对此答案发表评论。