为什么颤振小部件不可变?

时间:2018-12-17 08:31:26

标签: mobile flutter immutability

我不明白为什么Flutter对象是不可变的。我在Flutter文档中尝试过,但是并没有帮助。如果有人可以帮助我,我会很感激。

而且,我两天前才开始颤抖,真棒。

2 个答案:

答案 0 :(得分:4)

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

  

StatefulWidget实例本身是不可变的,并存储它们   可变状态,可以在由   createState方法或该状态所订阅的对象中的   引用的示例Stream或ChangeNotifier对象   存储在StatefulWidget本身的最终字段中。

     

每当膨胀StatefulWidget时,框架就会调用createState,   这意味着多个状态对象可能与   如果该窗口小部件已插入树中,则为相同的StatefulWidget   多个地方。同样,如果将StatefulWidget从   树,然后再次插入到树中,框架将调用   再次使用createState创建新的State对象,从而简化了   状态对象的生命周期。

     

一个StatefulWidget从一个移动时保持相同的State对象   如果其创建者使用GlobalKey作为   它的关键。因为具有GlobalKey的小部件最多可以用于   在树中的某个位置,使用GlobalKey的小部件最多具有一个   相关元素。框架利用了此属性   从树中的一个位置移动带有全局键的小部件时   通过嫁接与此相关的(唯一)子树来移植到另一个   从旧位置到新位置的窗口小部件(而不是   在新位置重新创建子树)。国家对象   与StatefulWidget关联的代码与其余的   子树,这意味着State对象被重用(而不是被   重新创建)。但是,为了有资格   嫁接时,必须将小部件插入到   从旧位置删除动画的框架相同。

     

性能注意事项

     

有两个主要类别   StatefulWidgets。

     

第一个是在State.initState和   在State.dispose中处理它们,但不依赖于   InheritedWidgets或调用State.setState。这种小部件很常见   用于应用程序或页面的根目录,并与之通信   通过ChangeNotifiers,Streams或其他此类对象的subwidget。   遵循这种模式的有状态小部件相对便宜(在   CPU和GPU周期的术语),因为它们是一次性构建的,因此永远不会   更新。因此,它们的构建可能有些复杂和深入   方法。

     

第二类是使用State.setState或依赖于   InheritedWidgets。这些通常会在   应用程序的生命周期,因此最小化   重建此类小部件的影响。 (他们也可以使用State.initState   或State.didChangeDependencies并分配资源,但是   重要的是它们要重建。)

“颤动对象”非常广泛。有不同种类的物体。

状态和窗口小部件被拆分,并且它们具有不同的生命周期。出于性能原因使用不变性。如果需要更改小部件,请相应地创建一个新实例。 比起两个实例的状态是否相同,检查两个实例是否相同的速度更快。

这是const经常使用的原因之一。如果构造函数参数相同,则可以确保使用相同的实例。

来自上面链接的文档

  

尽可能使用const小部件。 (这等效于缓存小部件并重新使用它。)

答案 1 :(得分:2)

不可变性是许多编程语言的基石,使用不可变数据可以使抖动更有效。利用此优势为每帧重建不可变视图树

通常,我们应该将重建工作放在实际更改的子树上

小部件树是用户界面的不变描述。我们如何在不从根本上重建的情况下重建其中的一部分?好吧,实际上,小部件树不是从父小部件到子小部件,从根到叶的引用的实体化树结构。特别是,StatelessWidget和StatefulWidget没有子引用。它们提供的是构建方法(在有状态的情况下,通过关联的State实例)。 Flutter框架递归地调用这些构建方法,同时生成或更新实际的运行时树结构,而不是小部件,而是引用小部件的Element实例。元素树是可变的,并由Flutter框架进行管理。

那么,当您在State实例s上调用setState时,实际发生了什么? Flutter框架标记了以s为根的子树,以进行重建。当下一帧到期时,该子树将根据s的build方法返回的小部件树进行更新,而该小部件树又取决于当前应用程序的状态