- State 的生命周期和 StatefulWidget 不同,当 StatefulWidget 状态改变后就会被重建,但是 State 不会改变,但是当 StatefulWidget 在 View 树中移除再插入又会生成新的 State。参考下文 State.context.
- 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的生命周期
总体介绍一下生命周期,大致可以看成三个阶段:
- 初始化(插入渲染树)
- 状态改变(在渲染树中存在)
- 销毁(从渲染树种移除)
先举 FavoriteWidget 为例,当这个 Widget 首次插入到树中时,框架会调用其 createState 函数以创建一个新的_FavoriteWidgetState实例来与该树中的相应位置关联(请注意,我们通常命名State子类时带一个下划线,这表示其是私有的)。 当这个widget的父级重建时,父级将创建一个新的FavoriteWidget实例,但是Flutter框架将重用已经在树中的_FavoriteWidgetState实例,而不是再次调用createState创建一个新的。
从 StatefulWidget调用createState之后,框架将新的状态对象插入树中,然后调用 State 的initState,接着如上图所示走了一遍自身的生命周期。需要注意的是,StatefulWidget 和 State 是不同的生命周期。
生命周期详解
initState
当插入渲染树的时候调用,这个函数在生命周期中只调用一次。这里可以做一些初始化工作,比如初始化State的变量。
didChangeDependencies
这个函数会紧跟在initState之后调用,并且可以调用BuildContext.inheritFromWidgetOfExactType,那么BuildContext.inheritFromWidgetOfExactType的使用场景是什么呢?
static TabController of(BuildContext context) {
final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope);
return scope?.controller;
}
实际上就是调用BuildContext.inheritFromWidgetOfExactType,也就说在didChangeDependencies中,可以跨组件拿到数据。
didUpdateWidget
当组件的状态改变的时候就会调用didUpdateWidget,比如调用了setState.
实际上这里flutter框架会创建一个新的Widget,绑定本State,并在这个函数中传递老的Widget。
这个函数一般用于比较新、老Widget,看看哪些属性改变了,并对State做一些调整。
需要注意的是,涉及到controller的变更,需要在这个函数中移除老的controller的监听,并创建新controller的监听。
deactivate
在dispose之前,会调用这个函数。
dispose
一旦到这个阶段,组件就要被销毁了,这个函数一般会移除监听,清理环境。‘
总结
阶段 | 调用次数 |
---|---|
构造函数 | 1 |
initState | 1 |
didChangeDependencies | >=1 |
didUpdateWidget | >=1 |
deactivate | >=1 |
dispose | 1 |
各个方法的解释:
- initState:插入渲染树时调用,只调用一次,widget创建执行的第一个方法,可以再里面初始化一些数据,以及绑定控制器
- didChangeDependencies:当State对象的依赖发生变化时会被调用;例如:在之前build() 中包含了一个InheritedWidget,然后在之后的build() 中InheritedWidget发生了变化,那么此时InheritedWidget的子widget的didChangeDependencies()回调都会被调用。InheritedWidget这个widget可以由父控件向子控件共享数据,案例可以参考 scoped_model开源库。
- build :它主要是用于构建Widget子树的,调用次数:多次,初始化之后开始绘制界面,当setState触发的时候会再次被调用
- didUpdateWidget:组件状态改变时候调用,可能会调用多次
- deactivate:当 State 被暂时从视图树中移除时,会调用这个函数。
页面切换时,也会调用它,因为此时 State 在视图树中的位置发生了变化,需要先暂时移除后添加。 - dispose():当State对象从树中被永久移除时调用;通常在此回调中释放资源。
- reassemble:此回调是专门为了开发调试而提供的,在热重载(hot reload)时会被调用,此回调在Release模式下永远不会被调用。