State
Flutter版本
Flutter (Channel stable, v1.12.13+hotfix.6, on Mac OS X 10.15 19A602, locale zh-Hans-CN)
The logic and internal state for a [StatefulWidget].
State is information that (1) can be read synchronously when the widget is built and (2) might change during the lifetime of the widget. It is the responsibility of the widget implementer to ensure that the [State] is promptly notified when such state changes, using [State.setState].
StatefulWidget的内部逻辑状态(state)。
这种状态(state)是一段信息,在widget完成build之后它可以被同步地读取,在widget的生命周期中这段信息可能会发生变化(might change,也可能是指是可变的)。widget的内部实现确保了当状态变化或调用了State.setState方法之后能及时准确地通知到State对象。
[State] objects are created by the framework by calling the [StatefulWidget.createState] method when inflating a [StatefulWidget] to insert it into the tree. Because a given [StatefulWidget] instance can be inflated multiple times (e.g., the widget is incorporated into the tree in multiple places at once), there might be more than one [State] object associated with a given [StatefulWidget] instance. Similarly, if a [StatefulWidget] is removed from the tree and later inserted in to the tree again, the framework will call [StatefulWidget.createState] again to create a fresh [State] object, simplifying the lifecycle of [State] objects.
framework在填充StatefulWidget并插入widget树时,会调用StatefulWidget.createState方法创建State对象。由于一个给定的StatefulWidget实例可能会被填充多次(比如,这个widget在很短的时间内在多个位置被包含进widget树中),所以可能会有一个以上的State对象与给定的StatefulWidget实例关联。当一个StatefulWidget从树中移除,之后又再次插入树中,framework会再次调用StatefulWidget.createState来创建一个新的State对象,以简化State对象的生命周期。
[State] objects have the following lifecycle:
* The framework creates a [State] object by calling [StatefulWidget.createState].
* The newly created [State] object is associated with a [BuildContext].
This association is permanent: the [State] object will never change its
[BuildContext]. However, the [BuildContext] itself can be moved around
the tree along with its subtree. At this point, the [State] object is
considered [mounted].
State对象有以下生命周期:
- framework 通过调用 StatefulWidget.createState 来创建一个 State 对象。
- 新创建的 State 对象会与一个 BuildContext 相关联。这种关联是永久性的:State 对象永远不会改变它的 BuildContext 。然后,BuildContext 自己可以带着它的子树围绕着树移动。这种情况下,它的 State 对象被看作是安装好的(mounted)。
* The framework calls [initState]. Subclasses of [State] should override
[initState] to perform one-time initialization that depends on the
[BuildContext] or the widget, which are available as the [context] and
[widget] properties, respectively, when the [initState] method is
called.
- 之后,framework 会调用 initState 方法。State 的子类应当继承 initState 方法来完成一些依赖于 BuildContext 或对应 widget 的一次性的初始化设置。
* The framework calls [didChangeDependencies]. Subclasses of [State] should
override [didChangeDependencies] to perform initialization involving
[InheritedWidget]s. If [BuildContext.dependOnInheritedWidgetOfExactType] is
called, the [didChangeDependencies] method will be called again if the
inherited widgets subsequently change or if the widget moves in the tree.
- 接着,framework 会调用 didChangeDependencies 。如果这个 State 使用到了 InheritedWidget 共享的数据,那么你需要继承 didChangeDependencies 方法来实现跟共享数据相关的初始化方法。当 BuildContext.dependOnInheritedWidgetOfExactType 方法(使用InheritedWidget时会用到的用来更新数据的方法)被调用,inherited widgets 发生了改变或者 widget 在树中移动了,framework 会再次调用didChangeDependencies 方法。
* At this point, the [State] object is fully initialized and the framework
might call its [build] method any number of times to obtain a
description of the user interface for this subtree. [State] objects can
spontaneously request to rebuild their subtree by callings their
[setState] method, which indicates that some of their internal state
has changed in a way that might impact the user interface in this
subtree.
- 此时,State 对象已完全地初始化了,然后framework 会调用它的 build 方法几次来获得一个对于其子树的用户界面的描述。当 State 对象调用 setState 方法时,如果其子widget树的内部状态发生了改变,与用户界面产生了冲突,它会自发地发起对其子树的 rebuild 请求。
* During this time, a parent widget might rebuild and request that this
location in the tree update to display a new widget with the same
[runtimeType] and [Widget.key]. When this happens, the framework will
update the [widget] property to refer to the new widget and then call the
[didUpdateWidget] method with the previous widget as an argument. [State]
objects should override [didUpdateWidget] to respond to changes in their
associated widget (e.g., to start implicit animations). The framework
always calls [build] after calling [didUpdateWidget], which means any
calls to [setState] in [didUpdateWidget] are redundant.
- 在这个过程中,它的父widget可能会 rebuild 并请求更新树的当前节点,来显示一个带有相同 runtimeType 和 相同 Widget.key 的 widget 。当这种情况发生时, framework 会更新 State 对象的 widget 属性来提交一个新的 widget,然后以前一个 widget 为参数调用 didUpdateWidget 方法来作为 State 对象改变关联 widget (比如,开始了一个隐式动画implicit animations)的回调。framework 总是会在调用 didUpdateWidget之后调用一次 build 方法,这意味着在 didUpdateWidget 中调用 setState 方法是多余的。
* During development, if a hot reload occurs (whether initiated from the
command line `flutter` tool by pressing `r`, or from an IDE), the
[reassemble] method is called. This provides an opportunity to
reinitialize any data that was prepared in the [initState] method.
- 在开发过程中,如果发生了hot reload,reassemble 方法会被调用。这个方法提供了一个重新初始化在 initState 方法中准备好了的任何数据的机会。
* If the subtree containing the [State] object is removed from the tree
(e.g., because the parent built a widget with a different [runtimeType]
or [Widget.key]), the framework calls the [deactivate] method. Subclasses
should override this method to clean up any links between this object
and other elements in the tree (e.g. if you have provided an ancestor
with a pointer to a descendant's [RenderObject]).
- 如果子树中包含的 State 对象被从树中移除了(比如,父节点创建了一个带有不同 runtimeType 或 不同 Widget.key 的 widget),framework 会调用 deactive 方法。子类应该继承该方法,并在其中清楚掉所有这个对象和其他树中 elements 的链接(比如,如果你提供了一个带有指向其descendant(后代,末裔)的 RenderObject 的指针的ancestor(祖先))。
* At this point, the framework might reinsert this subtree into another
part of the tree. If that happens, the framework will ensure that it
calls [build] to give the [State] object a chance to adapt to its new
location in the tree. If the framework does reinsert this subtree, it
will do so before the end of the animation frame in which the subtree was
removed from the tree. For this reason, [State] objects can defer
releasing most resources until the framework calls their [dispose]
method.
- 在这种情况下,framework 可能会将这段子树重新插入到树的另一个部分,如果这种情况发生了,framework 会确保它会调用 build 方法来给 State 对象一个适应它在树中新位置的机会。如果 framework 需要重新插入这段子树,它会在子树从树中移除的动画帧结束之前进行这个操作。所以 State 对象可以安全地等到 framework 调用它的 dispose 方法时再进行资源的释放。
* If the framework does not reinsert this subtree by the end of the current
animation frame, the framework will call [dispose], which indicates that
this [State] object will never build again. Subclasses should override
this method to release any resources retained by this object (e.g.,
stop any active animations).
- 如果 framework 没有在动画帧结束之前进行重新插入的动作,它就会调用 dispose 方法,这个意味着这个 State 对象不会再被 build 。子类应当继承这个方法来释放被这个对象持有的任何资源(比如,停掉所有active的动画)。
* After the framework calls [dispose], the [State] object is considered
unmounted and the [mounted] property is false. It is an error to call
[setState] at this point. This stage of the lifecycle is terminal: there
is no way to remount a [State] object that has been disposed.
- 当 framework 调用了 dispose 方法,这个 State 对象就被视为已卸载,同时其mounted 属性也会被置为 false 。如果在这种情况下调用 setState 方法就会产生异常。这是State对象整个生命周期的终结:一个已经被 dispose 的State对象,不会有任何办法再将其remount。