initState():当Widget第一次插入到Widget树中时被调用。对于每一个State对象,Flutter framework只会调用一次该方法。所以这个回调适合做一些变量的初始化,订阅子树的事件通知等。不能在该回调中调用BuildContext.dependOnInheritedWidgetOfExactType方法(该方法用于获取在Widget树上离当前Widget最近的一个父级InheritedWidget),原因在于初始化完成之后,InheritedWidget也可能会发生变化,所以此时获取就不一定正确。正确的时间是在build() 或者 didChangeDependences() 方法中获取。
didChangeDependences(): 当State对象的依赖发生变化时会调用该方法。
build(): 构建Widget子树时会调用。
1)在调用initState() 之后。
2)在调用didUpdateWidget()之后。
3)在调用setState()之后。
4)在调用didChangeDependences()之后。
5)在State对象从树中的一个位置移除移除后,又重新插入到树的其他位置之后。
reassemble():此回调专门为开发调试提供,在热重载会被调用,在Release模式下不会调用。
didUpdateWidget(): 此回调在Widget重新创建时调用。Flutter framework会调用Widget.canUpdate() 来检测Widget树中同一位置的新旧节点,然后决定是否需要更新,如果Widget.canUpdate()返回True,则调用此回调。
deactivate(): 当State对象从树中被移除时。在一些场景下,Flutter framework 会将State对象重新插入到树中,比如包含此对象的子树从树的一个位置移动到另外一个位置(可以通过GlobalKey来实现)。如果移除后没有重新插入到树中则紧接着会调用dispose() 方法。
dispose(): 当State对象永久被移除时调用。通常此方法可以用来释放资源。
下面是生命周期图:
在Widget树中获取State对象
通过Context获取
Context对象又一个findAncestorStateOfType() 方法,该方法可以从当前节点沿着Widget树向上查找制定类型的State对象。如下:
ScaffoldState _state = context.findAncestorStateOfType<Scaffold>();
一般来说,如果StatefulWidget的状态是私有的(不应该向外部暴露),那么我们代码中就不应该去直接获取其State对象;如果StatefulWidget的状态是希望暴露出的(通常还有一些组件的操作方法),我们则可以去直接获取其State对象。但是通过context.findAncestorStateOfType获取StatefulWidget的状态的方法是通用的,我们并不能在语法层面指定StatefulWidget的状态是否私有,所以在Flutter开发中便有了一个默认的约定:如果StatefulWidget的状态是希望暴露出的,应当在StatefulWidget中提供一个of静态方法来获取其State对象,开发者便可直接通过该方法来获取;如果State不希望暴露,则不提供of方法。这个约定在Flutter SDK里随处可见。所以,上面示例中的Scaffold也提供了一个of方法,我们其实是可以直接调用它的:
ScaffoldState _state = Scaffold.of(context);
通过GlobalKey
GlobalKey.currentState;
GlobalKey 是Flutter提供的一种在整个APP中引用element的机制。如果Widget设置了key属性,则可以通过globalKey.currentWidget获得该widget对象、globalKey.currentElement来获得widget对应的element对象,如果当前widget是StatefulWidget,则可以通过globalKey.currentState来获得该widget对应的state对象