简体   繁体   English

StatefulWidget 和 StatelessWidget 的 Flutter 性能

[英]Flutter performance of StatefulWidget and StatelessWidget

I use a lot StatelessWidgets when I have to create "templates" of widgets that are used multiple times inside my app because the docs say so:当我必须创建在我的应用程序中多次使用的小部件的“模板”时,我使用了很多 StatelessWidgets,因为文档是这样说的:

Stateless widget are useful when the part of the user interface you are describing does not depend on anything other than the configuration information in the object itself and the BuildContext in which the widget is inflated.当您描述的用户界面部分不依赖于对象本身的配置信息和小部件在其中膨胀的 BuildContext 之外的任何其他内容时,无状态小部件很有用。

Here is an example:下面是一个例子:

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
    );
  }

}

The above is good because I can use const StepInputButton(val, "val"), in the code with CONST which improves performances.以上很好,因为我可以在带有 CONST 的代码中使用const StepInputButton(val, "val"),来提高性能。


PROBLEM问题

I am using the famous Provider widget to manage the state and the page of my apps usually look like this:我正在使用著名的Provider小部件来管理状态,我的应用程序页面通常如下所示:

class SuccessPage extends StatelessWidget {

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

}

That's a page of my app with Scaffold that has a Drawer, a float action button and an appTitle.这是我的带有 Scaffold 的应用程序页面,它有一个抽屉、一个浮动操作按钮和一个 appTitle。 Here I use a StatelessWidget because I do not use setState() since provider does all the work for me.在这里,我使用 StatelessWidget,因为我不使用 setState(),因为 provider 为我完成了所有工作。 But still in the official flutter doc they say:但他们仍然在官方颤振文档中说:

For compositions that can change dynamically, eg due to having an internal clock-driven state, or depending on some system state, consider using StatefulWidget.对于可以动态更改的组合,例如由于具有内部时钟驱动状态或取决于某些系统状态,请考虑使用 StatefulWidget。

So do I have to change class SuccessPage extends StatelessWidget to class SuccessPage extends StatefulWidget ?那么我是否必须将class SuccessPage extends StatelessWidget更改为class SuccessPage extends StatefulWidget Do I get advantages?我有优势吗?

Note : if you want to put the question in another way: should I use StatefulWidgets to create "app pages" whose state is going to change and StatelessWidgets for "reusable widgets" whose state doesn't change?注意:如果您想以另一种方式提出问题:我应该使用 StatefulWidgets 来创建状态将发生变化的“应用程序页面”,而使用 StatelessWidgets 来创建状态不会改变的“可重用小部件”吗?

StatefulWidget is necessary for when the widget itself is maintaining its own state.当小部件本身维护自己的状态时, StatefulWidget是必需的。 In the example you gave, the Provider package is handling the state for you, assuming you're using the correct provider type higher up the widget tree (for example, ChangeNotifierProvider ).在您提供的示例中, Provider包正在为您处理状态,假设您使用的是小部件树上方的正确提供程序类型(例如, ChangeNotifierProvider )。 There also doesn't seem to be anything in this code that would benefit from having access to the widget's lifecycle, so you wouldn't need access to methods like initState or dispose .这段代码中似乎也没有任何内容可以从访问小部件的生命周期中受益,因此您不需要访问initStatedispose类的方法。

As such, there's nothing for the widget itself to manage, so converting your class to be stateful is unnecessary.因此,小部件本身无需管理任何内容,因此无需将您的类转换为有状态的。

One thing I might suggest, though, is to use a Consumer instead of calling Provider.of directly.不过,我可能建议的一件事是使用Consumer而不是直接调用Provider.of A Consumer handles the call for you and removes any ambiguity on whether your widget will get updated when the Provider detects a state change. Consumer为您处理调用,并消除关于当Provider检测到状态更改时您的小部件是否会更新的任何歧义。

Keeping it simple:保持简单:

  1. If you have non- final global variables in your widget then you need a StatefulWidget如果您的小部件中有final全局变量,那么您需要一个StatefulWidget
  2. If all global variables are final then you should use StatelessWidget ;如果所有全局变量都是final那么你应该使用StatelessWidget

Reason:原因:

  1. If your global variable is non final that means it is allowed to change and if it's value is changed that means state of your object(Widget) is changed (basic oops concept I am talking about).如果您的全局变量是非最终变量,则意味着它可以更改,如果它的值发生更改,则意味着您的对象(小部件)的状态已更改(我正在谈论的基本 oops 概念)。 In such case you would like to call build method of your widget so that your changes get applied on the UI (if it matters for your UI).在这种情况下,您希望调用小部件的 build 方法,以便将您的更改应用于 UI(如果这对您的 UI 很重要)。 We do it by calling setState();我们通过调用setState(); and so we use StatefulWidget for such use-case.因此我们将StatefulWidget用于此类用例。
  2. If it is enough that once you initialize your global variable in constructor, you don't need to assign it any value in future then in such case use StatelessWidget .如果在构造函数中初始化全局变量就足够了,以后不需要为其分配任何值,那么在这种情况下使用StatelessWidget

I have tried to keep it very simple and not technical enough so, if you still have any doubts please comment on this answer .我试图保持它非常简单并且不够技术,所以如果您仍然有任何疑问,请对此答案发表评论

You use StatelessWidget for widgets that don't change their state, that will stay the same all the time.您将StatelessWidget用于不更改其状态的小部件,这些小部件将始终保持不变。 Example, appBar is stateless.. The build(...) function of the StatelessWidget is called only once and no amount of changes in any Variable(s) , Value(s) or Event(s) can call it again.例如, appBar是无状态的。 StatelessWidgetbuild(...)函数仅被调用一次,并且任何Variable(s)Value(s)Event(s)中的任何更改都不能再次调用它。

Therefore, when you need to change state(ex value) then use StatefulWidgets , basically StatelessWidget is used for building UI widgets that are static因此,当您需要更改 state(ex value) 然后使用StatefulWidgets ,基本上StatelessWidget用于构建静态的 UI 小部件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM