Flutter 中的有状态和无状态小部件之间的关系是啥?

Posted

技术标签:

【中文标题】Flutter 中的有状态和无状态小部件之间的关系是啥?【英文标题】:What is the relation between stateful and stateless widgets in Flutter?Flutter 中的有状态和无状态小部件之间的关系是什么? 【发布时间】:2018-05-10 03:32:09 【问题描述】:

有状态小部件被定义为在其生命周期内改变其状态的任何小部件。但是对于StatelessWidget,将StatefulWidget 作为其子级之一是一种非常常见的做法。如果StatefulWidget 是它的孩子之一,StatelessWidget 不会变成有状态的吗?

我尝试查看文档作为 StatelessWidget 代码的一部分,但无法弄清楚 StatelessWidget 如何将 Statefulwidget 作为其子级并仍然保留 StatelessWidget

Flutter中有状态和无状态的widget有什么关系和区别?

【问题讨论】:

您可以从不同类型的小部件组合布局,但这并不意味着您继承了组合的特性来影响每个小部件。我的意思是你可以有一个无状态的容器,它有另一个容器的子级,在其他地方声明为 StatefulWidget,容器的状态只会影响这个组件。所以,这一切都是为了让不同类型的小部件组合在一起,每个小部件都可以根据需要发挥作用。 更麻烦的是,还有第三种类型的小部件:InheritedWidget;哪个可以使StatelessWidget更新。 【参考方案1】:

StatelessWidget 永远不会重建自身(但可以来自外部事件)。 StatefulWidget 可以。这是黄金法则。

但是任何类型的小部件都可以重绘任何时候。

Stateless 仅仅意味着它的所有属性都是不可变的 并且改变它们的唯一方法是创建该小部件的新实例。它没有例如锁定小部件树。

但你不应该关心你的孩子是什么类型的。它对你没有任何影响。

【讨论】:

(相对较新的框架)。 rebuildrepaint有什么区别 同样来自flutter框架代码中的cmets,显然StateFulWidgets也是不可变的。 widget的构建基本上是调用"build"方法,然后创建/更新对应的renderbox;其次是绘画过程。这将在屏幕上打印这些渲染框。 继承“StatefulWidget”的类是不可变的。但是状态 (State) 本身是可变的。 @RémiRousselet 根据flutter.dev/docs/get-started/flutter-for/…,有状态和无状态小部件都会在每一帧中重建。【参考方案2】:

来自flutter.io的文档:

...这里要注意的重要一点是,无状态和有状态小部件的核心行为相同。他们重建每一帧,不同的是 StatefulWidget 有一个 State 对象,它跨帧存储状态数据并恢复它。

如果您有疑问,请始终记住这条规则:如果小部件发生变化(例如,用户与其交互),它就是有状态的。但是,如果一个子级对更改做出反应,如果父级没有对更改做出反应,则包含的父级仍然可以是无状态小部件。

【讨论】:

【参考方案3】:

正如颤振文档中提到的那样

有什么意义?

有些小部件是有状态的,有些是无状态的。 如果一个小部件发生变化——例如用户与之交互——它是有状态的。 小部件的状态由可以更改的值组成,例如滑块的当前值或复选框是否被选中。 小部件的状态存储在 State 对象中,将小部件的状态与其外观分开。 当小部件的状态发生变化时,状态对象调用 setState(),告诉框架重绘小部件。

无状态小部件没有要管理的内部状态。 Icon、IconButton 和 Text 是无状态小部件的示例,它们是 StatelessWidget 的子类。

有状态小部件是动态的。用户可以与有状态的小部件进行交互(例如,通过输入表单或移动滑块),或者它随时间而变化(可能是数据馈送导致 UI 更新)。 Checkbox、Radio、Slider、InkWell、Form 和 TextField 是有状态小部件的示例,它们是 StatefulWidget 的子类。

https://flutter.io/tutorials/interactive/#stateful-stateless

【讨论】:

【参考方案4】:

无状态小部件是静态小部件。在初始化无状态小部件之前,您只需要传递一些属性。它们不依赖于任何数据更改或任何行为更改。例如。 Text、Icon、RaisedButton 是无状态的小部件。

有状态小部件是动态小部件,它们可以在运行时根据用户操作或数据更改进行更新。 如果一个 Widget 可以在运行时改变它的状态,那么它就是有状态的 Widget。

2018 年 15 月 11 日编辑

无状态小部件可以在输入/外部数据发生变化时重新渲染(外部数据是通过构造函数传递的数据)。因为Stateless Widgets没有状态,所以只会渲染一次,不会自己更新,只会在外部数据变化时更新。

Stateful Widgets 具有内部状态,并且可以在输入数据更改或 Widget 的状态更改时重新渲染。

无状态和有状态小部件都有不同的生命周期。

【讨论】:

即使在将新数据从外部传递到 Stateless 小部件后,我们也可以在运行时更改它,但它不称为 Stateful 小部件(与您的最后一行相反)。 您能否解释一下无状态小部件如何“在外部数据更改时更新”? (“外部数据是通过构造函数传递的数据”。)构造函数不仅会被调用一次吗?通过构造函数传递的数据如何变化?【参考方案5】:

我可以想到一个非常简单的类比。你有一些家具,里面有书籍、装饰品和一台电视机。家具是无国籍的,它什么也不做不动。在电视的另一边,您可以打开、关闭、更改频道、播放电影(如果它连接了一些 DVD)等。电视有一个内部状态,它会影响它的行为方式。在家具中你没有状态。家具中电视的存在并没有增加它的状态。 希望这会有所帮助。

【讨论】:

这不能回答提问者的具体问题。 这是一个很好的类比!【参考方案6】:

状态是 (1) 可以在构建小部件时同步读取的信息,以及 (2) 可能在小部件的生命周期内发生变化的信息。小部件实现者有责任使用 State.setState 确保在此类状态发生更改时及时通知状态。

StatefulWidget:

有状态小部件是一种通过构建更具体地描述用户界面的其他小部件来描述部分用户界面的小部件。构建过程递归地继续,直到用户界面的描述完全具体(例如,完全由描述具体 RenderObjects 的 RenderObjectWidgets 组成)。

当您描述的用户界面部分可以动态更改时,有状态小部件很有用,例如由于具有内部时钟驱动状态,或取决于某些系统状态。对于仅依赖于对象本身的配置信息和小部件在其中膨胀的 BuildContext 的组合,请考虑使用 StatelessWidget。

StatefulWidget 实例本身是不可变的,并将其可变状态存储在由 createState 方法创建的单独 State 对象中,或者存储在该 State 订阅的对象中,例如 Stream 或 ChangeNotifier 对象,其引用存储在 final 字段中在 StatefulWidget 本身上。

StatelessWidget:

无状态小部件是一种通过构建更具体地描述用户界面的其他小部件来描述部分用户界面的小部件。构建过程递归地继续,直到用户界面的描述完全具体(例如,完全由描述具体 RenderObjects 的 RenderObjectWidgets 组成)。

当您描述的用户界面部分不依赖于对象本身中的配置信息和小部件膨胀所在的 BuildContext 之外的任何其他内容时,无状态小部件很有用。对于可以动态变化的构图,例如由于具有内部时钟驱动状态,或者取决于某些系统状态,请考虑使用 StatefulWidget。

【讨论】:

【参考方案7】:

在编写应用程序时,您通常会编写新的小部件,它们是 StatelessWidget 或 StatefulWidget 的子类

以下是StatelessWidgetStatefulWidget 小部件之间的一些区别:

无状态小部件:

    具有不可变状态的小部件。 无状态小部件是静态小部件。 它们不依赖于任何数据更改或任何行为更改。 Stateless Widget 没有状态,只会渲染一次,不会自行更新,只会在外部数据发生变化时更新。 例如:TextIconRaisedButton 是无状态小部件。

有状态小部件:

    具有可变状态的小部件。 有状态小部件是动态小部件。 它们可以在运行时根据用户操作或数据更改进行更新。 有状态的 Widget 有一个内部状态,如果输入数据发生变化或 Widget 的状态发生变化,它可以重新渲染。 例如:CheckboxRadio ButtonSlider 是有状态的小部件

【讨论】:

两个标题使用相同的名称:第二个是有状态的小部件。 现在我改变了,@SourabhMore 感谢您的指示【参考方案8】:

Answer for the Stack Overflow question - statefulness vs statelessness.

在 Flutter 中,不同之处在于无状态小部件可以由所有构造函数参数单独定义。如果您使用相同的参数创建两个无状态小部件,那么它们将是相同的。

然而,有状态的小部件不一定与使用相同构造函数参数构建的另一个小部件相同。它可能处于不同的状态。 实际上,有状态 widget 本身是不可变的(无状态),但 Flutter 管理一个单独的状态 object 并将其与小部件相关联,如 StatefulWidget doc 中所述。这意味着当 Flutter 重建一个有状态的小部件时,它会检查它是否应该重用以前的状态对象,如果需要,会将该状态对象附加到小部件。

父控件是无状态的,因为它不关心子控件的状态。有状态的孩子本身(或技术上的 Flutter)将处理自己的状态。 在高层次上,我同意这使父窗口小部件有状态,因为两个父母可能包含两个具有不同状态的孩子,因此在技术上它们本身是不同的。但是从 Flutter 的角度来看,它构建父 widget 时不关心 state,只有在构建 child 时才会考虑它的 statefull。

【讨论】:

【参考方案9】:

无状态:小部件状态只创建一次,然后它可以更新值但不能显式更新状态。从那里的结构也很清楚。这就是为什么它只有一个以StatelessWidget 扩展的类。因此,如果我说,他们将永远无法重新运行 build() 方法。

有状态:小部件可以在事件触发时多次更新其状态(本地)和值。这就是原因,实现方式也不同。在此,我们有 2 个类,一个是 StatefulWidget,另一个是状态实现处理程序,即 State<YourWidget>。因此,如果我说,他们可以根据触发的事件一次又一次地重新运行 build() 方法。

下图会有所帮助。

【讨论】:

【参考方案10】:

什么是有状态和无状态小部件?

TL;DR:允许您刷新屏幕的小部件是有状态小部件。没有的小部件是无状态的。

更详细地说,内容可以更改的动态小部件应该是有状态小部件。无状态小部件只能在参数更改时更改内容,因此需要在其在小部件层次结构中的位置点之上完成。包含静态内容的屏幕或小部件应该是无状态小部件,但要更改内容,则需要有状态。

我在一个有趣的媒体故事中发现了这个相关内容。不客气!

【讨论】:

【参考方案11】:

简单来说:

正如我们所知,每个小部件都是 Flutter 中的一个视图。其中有自己的类。当我们使用这些类时,我们会创建它的一个对象。我们为它们的不同变量/属性赋予值。前任。我们正在创建文本小部件,因此我们可以给它字符串、颜色、字体大小、字体系列。所以通过给出这个,我们在创建它的同时定义它的属性。到目前为止,无状态或有状态小部件是相同的,但是,

当我们想要一次又一次地更改/更新它的属性(比如字符串或颜色)时,它应该是有状态的小部件。

当我们在第一次定义它是无状态小部件后不想更改它的属性时。

这意味着我们关心小部件保存/控制/显示的数据。

所以无状态是数据少,有状态是数据满。

现在,如果您定义一个无状态的类,这意味着该类不关心/在其中包含变量,或者说它自己的类中的数据,即类级别,但它可能有另一个关心数据的小部件/类,即它是有状态的。所以不会互相影响。

如果我在这里错了,请纠正我。

【讨论】:

【参考方案12】:

免责声明 :- 从上周开始研究 Flutter :)

statelessstatefull 小部件有自己的生命周期来创建和更新 UI。但是,您可以使用无状态或有状态来呈现 UI,但实际上,当 ui 完全或部分依赖于外部数据(例如 - 使用 api 呈现列表)而使用无状态小部件像任何输入屏幕一样呈现静态 ui 时,有状态更方便一个很好的做法。

【讨论】:

我认为作者的意思是相反的:·D【参考方案13】:

什么是有状态和无状态小部件?

无状态小部件:无状态小部件仅在父级更改时构建。

Stateful Widgets : Stateful Widgets 保存了该小部件的状态,并且可以在状态改变时重建。

【讨论】:

以上是关于Flutter 中的有状态和无状态小部件之间的关系是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter/Dart:我的小部件树中可以有多个带有状态的小部件吗?

Flutter:如何从浮动操作按钮调用小部件状态类的方法

从另一个小部件更改一个小部件中的状态

如何从另一个 dart 文件中调用有状态小部件(有表单)方法?- Flutter

从另一个有状态小部件调用一个有状态小部件中的方法 - Flutter

如何更新导航抽屉中的有状态小部件,同时在 Android 中保持与片段相同的类?