Flutter - State类

写了这么多,无非就是State文档贴过来,最有感触的就两点:

  1. State 的生命周期和 StatefulWidget 不同,当 StatefulWidget 状态改变后就会被重建,但是 State 不会改变,但是当 StatefulWidget 在 View 树中移除再插入又会生成新的 State。参考下文 State.context.
  2. initState -> build -> 状态改变 -> didUpdateWidget -> build --->移除.

在学习 flutter 的时候,总会用到 StatefulWidget,它是一个有状态的 widget,会根据不同状态有不同显示,它的生命周期与 State 有关,它的基本写法如下

// flutter官方教程里面的一个类,点击一个关注的星星,然后就表明已经关注。再点击表示不再关注,默认状态是已关注,关注数是41
class FavoriteWidget extends StatefulWidget {
  @override
  _FavoriteWidgetState createState() => new _FavoriteWidgetState();
}
class _FavoriteWidgetState extends State<FavoriteWidget> {
  bool _isFavorited = true;
  int _favoriteCount = 41;

  void _toggleFavorite() {
    setState(() {
      // If the lake is currently favorited, unfavorite it. Otherwise, favorite it.
        _favoriteCount = _isFavorited?_favoriteCount -1:_favoriteCount +1 ;
        _isFavorited = !_isFavorited;
    });
  }
  @override
  Widget build(BuildContext context) {
    return new Widget(
        // build by states
    );
  }
}

将 FavoriteWidget 插入到 Views 树中的时候,每当调用 States.setState() 时,都会重新build一次FavoriteWidget ,然后将新的 Views代替原先的,并显示给用户。

您可能想知道为什么 StatefulWidget 和 State 是单独的对象。在 Flutter 中,这两种类型的对象具有不同的生命周期: Widget 是临时对象,用于构建当前状态下的应用程序,而 State 对象在多次调用build()之间保持不变,允许它们记住信息(状态)。

那么首先得知道,State的生命周期是什么?

一、生命周期

转载自jzoom_flutter中的生命周期.png

突然看到这个图,可能会有点懵,因为许多方法都不清是干什么的,稍后会慢慢讲解,不耐烦的可以跳到最后每个方法的总结,这里先总体介绍一下生命周期,大致可以看成三个阶段:

  • 初始化(插入渲染树)
  • 状态改变(在渲染树中存在)
  • 销毁(从渲染树种移除)

先举 FavoriteWidget 为例,当这个 Widget 首次插入到树中时,框架会调用其 createState 函数以创建一个新的_FavoriteWidgetState实例来与该树中的相应位置关联(请注意,我们通常命名State子类时带一个下划线,这表示其是私有的)。 当这个widget的父级重建时,父级将创建一个新的FavoriteWidget实例,但是Flutter框架将重用已经在树中的_FavoriteWidgetState实例,而不是再次调用createState创建一个新的。

从 StatefulWidget 调用createState之后,框架将新的状态对象插入树中,然后调用 State 的initState,接着如上图所示走了一遍自身的生命周期。需要注意的是,StatefulWidget 和 State 是不同的生命周期。

二、State 源文档翻译

State 是当 Widget 被渲染或者在其生命周期中状态改变时,能同步读到相关信息的对象。当实例StatefulWidget 时(下文说的 Widget 无特别说明,都是StatefulWidget 懒得打),必须保证能正确使用 State.setState 来告知该 Widget的状态发生了变化。

当渲染这个 Widget 并将其插入View 树中,会调用 StatefulWidget.createState 然后,framework 就会创建一个 State 对象。 因为一个 Widget 可以被 inflated 多次,比如说 这个 FavoriteWidget 可以被多个地方用到,所以这里会存在多个 _FavoriteWidgetState 与之绑定。同样,当 Widget 被移除出 Views 树的时候,然后又重新插入,这时候 framework 会再次调用StatefulWidget.createState 来创建一个新的 State 对象。
State 的生命周期如下:

  • The framework creates a State object by calling StatefulWidget.createState.
  • 这个新的 State 对象将会绑定一个 BuildContext ,这个绑定是永久的。 State 永远也不会改变其 BuildContext (所以它的属性中,contenxt是只读的。可以把这个理解成 Widget 在 Views 树中的位置,文档中是 The location in the tree where this widget builds.)但是, BuildContext 自身却是可以改变的,可以因为 Widget 在树中的位置变化而变化。由此,State 有一个属性是 mounted 表明 State 当前是否正确绑定在View树中。当创建 State 对象,并在调用 State.initState 之前,framework 会根据 BuildContext 来标记 mounted,然后在 State的生命周期里面,这个 mounted 属性不会改变,直至 framework 调用 State.dispose,当改变之后, State 对象再也不会调用 build 方法,而且当 mounted = false 时,调用 State.setState 会报错。
  • The framework calls initState. 在State 生命周期中只会调用一次。
  • The framework calls didChangeDependencies. 一般是在初始化中调用,但是如果BuildContext.inheritFromWidgetOfExactType 被调用,那么当widgets 改变或者是在 Views 树中移动,didChangeDependencies将会再一次调用。
  • 当 State 完全初始化后,framework 会多次调用 build来获取绑定的实例化 Widget 的信息。同时,当调用 setState 方法时,State 会自发的重建 Widget 的子 Views。
  • 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.
  • 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.
  • f 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).
  • 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.
  • 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).
  • After the framework calls dispose, the State object is considered unmounted and the mountedproperty 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.
名称 返回值/类型 意义
context read-only BuildContext The location in the tree where this widget builds.
mounted read-only bool Whether this State object is currently in a tree.
widget read-only T The current configuration.
hashCode read-only, inherited int The hash code for this object.
runtimeType read-only, inherited Type A representation of the runtime type of the object.
build(BuildContext context) Widget Describes the part of the user interface represented by this widget.
deactivate() void Called when this object is removed from the tree.
debugFillProperties(DiagnosticPropertiesBuilder properties) void Add additional properties associated with the node.
didChangeDependencies() void Called when a dependency of this State object changes.
didUpdateWidget(T oldWidget) void Called whenever the widget configuration changes.
dispose() void Called when this object is removed from the tree permanently.
initState() void Called when this object is inserted into the tree.
reassemble() void Called whenever the application is reassembled during debugging, for example during hot reload.
setState (VoidCallback fn) void Notify the framework that the internal state of this object has changed.

参考资料:
https://docs.flutter.io/flutter/widgets/State-class.html
https://segmentfault.com/a/1190000015211309 推举

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335