简体   繁体   English

为什么扑动的小部件是不可变的?

[英]Why are flutter widgets immutable?

I am not able to understand why Flutter objects are immutable. 我无法理解为什么Flutter对象是不可变的。 I tried it in the Flutter docs but they weren't that helpful. 我在Flutter文档中尝试过,但它们并没有那么有用。 If anyone can help me with this, I'll be thankful. 如果有人能帮我这个,我会感恩的。

Also, I just started flutter 2 days ago and it's awesome. 另外,我刚刚开始在2天前开始颤抖,这太棒了。

From https://docs.flutter.io/flutter/widgets/StatefulWidget-class.html 来自https://docs.flutter.io/flutter/widgets/StatefulWidget-class.html

StatefulWidget instances themselves are immutable and store their mutable state either in separate State objects that are created by the createState method, or in objects to which that State subscribes, for example Stream or ChangeNotifier objects, to which references are stored in final fields on the StatefulWidget itself. StatefulWidget实例本身是不可变的,并且将它们的可变状态存储在由createState方法创建的单独State对象中,或者存储在State订阅的对象中,例如Stream或ChangeNotifier对象,其引用存储在StatefulWidget的最终字段中本身。

The framework calls createState whenever it inflates a StatefulWidget, which means that multiple State objects might be associated with the same StatefulWidget if that widget has been inserted into the tree in multiple places. 框架在膨胀StatefulWidget时调用createState,这意味着如果该窗口小部件已插入到多个位置的树中,则多个State对象可能与同一StatefulWidget关联。 Similarly, if a StatefulWidget is removed from the tree and later inserted in to the tree again, the framework will call createState again to create a fresh State object, simplifying the lifecycle of State objects. 类似地,如果从树中删除StatefulWidget并稍后再次插入树中,则框架将再次调用createState以创建新的State对象,从而简化State对象的生命周期。

A StatefulWidget keeps the same State object when moving from one location in the tree to another if its creator used a GlobalKey for its key. 如果StatefulWidget的创建者使用GlobalKey作为其键,则StatefulWidget在从树中的一个位置移动到另一个位置时保持相同的State对象。 Because a widget with a GlobalKey can be used in at most one location in the tree, a widget that uses a GlobalKey has at most one associated element. 由于具有GlobalKey的窗口小部件可以在树中的至多一个位置使用,因此使用GlobalKey的窗口小部件最多只有一个关联元素。 The framework takes advantage of this property when moving a widget with a global key from one location in the tree to another by grafting the (unique) subtree associated with that widget from the old location to the new location (instead of recreating the subtree at the new location). 当通过将与该窗口小部件关联的(唯一)子树从旧位置移植到新位置(而不是在该位置重新创建子树)时,框架利用此属性将带有全局键的窗口小部件从树中的一个位置移动到另一个位置。新的位置)。 The State objects associated with StatefulWidget are grafted along with the rest of the subtree, which means the State object is reused (instead of being recreated) in the new location. 与StatefulWidget关联的State对象与子树的其余部分一起被移植,这意味着State对象在新位置被重用(而不是被重新创建)。 However, in order to be eligible for grafting, the widget must be inserted into the new location in the same animation frame in which it was removed from the old location. 但是,为了有资格进行嫁接,必须将窗口小部件插入到从旧位置移除它的同一动画帧中的新位置。

Performance considerations 性能考虑因素

There are two primary categories of StatefulWidgets. StatefulWidgets有两个主要类别。

The first is one which allocates resources in State.initState and disposes of them in State.dispose, but which does not depend on InheritedWidgets or call State.setState. 第一个是在State.initState中分配资源并在State.dispose中处理它们,但它不依赖于InheritedWidgets或调用State.setState。 Such widgets are commonly used at the root of an application or page, and communicate with subwidgets via ChangeNotifiers, Streams, or other such objects. 此类窗口小部件通常在应用程序或页面的根目录中使用,并通过ChangeNotifiers,Streams或其他此类对象与子窗口小部件进行通信。 Stateful widgets following such a pattern are relatively cheap (in terms of CPU and GPU cycles), because they are built once then never update. 遵循这种模式的有状态小部件相对便宜(就CPU和GPU周期而言),因为它们构建一次然后永不更新。 They can, therefore, have somewhat complicated and deep build methods. 因此,它们可能有一些复杂和深刻的构建方法。

The second category is widgets that use State.setState or depend on InheritedWidgets. 第二类是使用State.setState或依赖于InheritedWidgets的小部件。 These will typically rebuild many times during the application's lifetime, and it is therefore important to minimize the impact of rebuilding such a widget. 这些通常会在应用程序的生命周期内重建多次,因此最小化重建此类窗口小部件的影响非常重要。 (They may also use State.initState or State.didChangeDependencies and allocate resources, but the important part is that they rebuild.) (他们也可以使用State.initState或State.didChangeDependencies并分配资源,但重要的是他们重建。)

"Flutter objects" is quite broad. “颤动的物体”非常广泛。 There are different kinds of objects. 有不同种类的对象。

State and widget are split and they have different lifecycles. 状态和窗口小部件是分开的,它们具有不同的生命周期。 Immutability is used for performance reasons. 出于性能原因,使用不变性。 If the widget needs to change, create a new instance set up accordingly. 如果窗口小部件需要更改,请相应地创建新的实例。 It's quicker to check if two instances are identical than if their state is the same. 检查两个实例是否相同,比它们的状态是否相同更快。

This is one of the reasons const is used often. 这是常用const的原因之一。 It ensures that identical instances are used if the constructor parameters are the same. 它确保在构造函数参数相同时使用相同的实例。

From the docs linked to above 从与上面链接的文档

Use const widgets where possible. 尽可能使用const小部件。 (This is equivalent to caching a widget and re-using it.) (这相当于缓存窗口小部件并重新使用它。)

Immutability is the cornerstone of many programming languages and using immutable data can be more efficient flutter Take this advantage to rebuild the immutable view tree for every frame 不可变性是许多编程语言的基石,使用不可变数据可以更有效地利用这一优势为每一帧重建不可变视图树

In general, we should confide rebuilding to the subtrees that actually change 一般来说,我们应该将重建倾向于实际改变的子树

The widget tree is an immutable description of the user interface. 窗口小部件树是用户界面的不可变描述。 How can we rebuild part of that without reconstructing it from the root? 如何在不从根重构的情况下重建其中的一部分? Well, in truth, the widget tree is not a materialized tree structure with references from parent widget to child widget, root to leaf. 实际上,小部件树不是具有从父小部件到子小部件,从根到叶的引用的物化树结构。 In particular, StatelessWidget and StatefulWidget don't have child references. 特别是,StatelessWidget和StatefulWidget没有子引用。 What they do provide are build methods (in the stateful case, via the associated State instances). 他们提供的是构建方法(在有状态的情况下,通过关联的State实例)。 The Flutter framework calls those build methods, recursively, while generating or updating an actual runtime tree structure, not of widgets, but of Element instances referring to widgets. Flutter框架以递归方式调用这些构建方法,同时生成或更新实际的运行时树结构,而不是小部件,而是引用小部件的Element实例。 The element tree is mutable, and managed by the Flutter framework. 元素树是可变的,由Flutter框架管理。

So what actually happens when you call setState on a State instance s? 那么当你在State实例上调用setState时会发生什么呢? The Flutter framework marks the subtree rooted at the element corresponding to s for a rebuild. Flutter框架标记以与s对应的元素为根的子树,用于重建。 When the next frame is due, that subtree is updated based on the widget tree returned by the build method of s, which in turn depends on current app state 当下一帧到期时,该子树将根据s的构建方法返回的窗口小部件树进行更新,而后者依赖于当前的应用程序状态

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

相关问题 Flutter - 单击时渲染新的小部件 - Flutter - Render new Widgets on click Flutter-通知列内的同级小部件 - Flutter - notify sibling widgets inside Column Flutter:在一堆小部件中结合 Draggable 和 GestureDetector - Flutter: combining Draggable and GestureDetector in a Stack of widgets Flutter:当其他小部件可用时,ListView 的高度会降低 - Flutter: ListView height is getting reduced when other widgets are available Flutter App targeting Android 12 CRASHES => FLAG_IMMUTABLE 或 FLAG_MUTABLE 在创建 PendingIntent 时指定 - Flutter App targeting Android 12 CRASHES => FLAG_IMMUTABLE or FLAG_MUTABLE to be specified when creating a PendingIntent 如何在仍然显示小部件的同时将我的 AppBar 放在 Flutter 中的单独文件中? - How can I have my AppBar in a separate file in Flutter while still having the Widgets show? flutter 类似悬停的触摸处理 - 无需抬起手指即可检测来自不同小部件的触摸 - flutter hover-like touch handling - detect touch from different widgets without lifting the finger 为什么颤振中的构建器在这里中断 - why is builder in flutter breaking here 为什么我的命名路由在 flutter 中没有按预期工作? - Why is my named routing is not working as expected In flutter? 为什么 Flutter 导入提供程序包不起作用? - Why is Flutter import provider package not working?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM