State生命周期
在学习Java开发Android时,我们需要学习各种Activity,Framgent的生命周期概念。Flutter也一样,Framework层为StatefulWidget对应的State定制了生命周期的回调方法,如下图所示:
那么,这些回调方法分别时在什么时候调用的呢?这部分内容博主建议不需要死记硬背,当然你一目十行当我没说,博主这里将通过例子并结合上图来说明。
class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void initState(){ super.initState(); print("initState"); } void didChangeDependencies(){ super.didChangeDependencies(); print("didChangeDependencies"); } void reassemble(){ super.reassemble();//热重载回调,release模式下不起作用 print("reassemble"); } @override void didUpdateWidget(MyHomePage oldWidget){ super.didUpdateWidget(oldWidget); print("didUpdateWidget"); } @override void deactivate(){ super.deactivate(); print("deactivate"); } @override void dispose() { // TODO: implement dispose super.dispose(); print("dispose"); } void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { print("build"); return Scaffold( appBar: AppBar( title: Text("生命周期"), actions: <Widget>[ new IconButton( icon: new Icon( Icons.navigate_next, color: Colors.white, ), onPressed: (){ Navigator.push( context, MaterialPageRoute( builder: (context)=>NextPageWidget() ) ); }), ], ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text("点击下面按钮进行自加操作"), Text("$_counter",style: Theme.of(context).textTheme.display1,), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: "自加", child: Icon(Icons.add), ), ); }
class NextPageWidget extends StatelessWidget{ @override Widget build(BuildContext context) { // TODO: implement build return Scaffold( appBar: AppBar(title:Text( "跳转页面"),), body: Center( child: Text("这个是第二页"), ), ); } }
执行这段代码后,也就是我们刚刚打开App的时候,我们看一下控制台输出如下内容:
由此可知,首次启动界面执行的顺序是:initState->didChangeDependencies->build。接着我们点击一下热重载,也就是Android Studio右上角闪电图标,控制台输出如下:
可以看出来,热重载后的执行顺序是:reassemble->didUpdateWidget->build。当然reassemble只在debug模式下有效,实际使用中是没有的。接着我们点击App右上角跳转界面,控制台输出如下:
可以看到跳转界面后,我们的执行顺序是:deactivate->didChangeDependencies->build。返回其实和跳转界面一样的输出,这里就不看了,同样是上图的顺序。
生命周期重要方法解释
(1)initState
initState是State生命周期里第一个执行的方法,在实际项目中,当我们需要追加一些初始化方法的时候可以用其执行,比如animations,controllers。如果要重写这个方法,就需要在这个方法里加上super.initState()。在initState里,Framework层还未把Context和State关联到一起,因此还不能访问Context。另外,初始化方法在生命周期里只会执行一次。
(2)didChangeDependencies
该方法在执行完initState之后被执行,这个时候可以访问Context了。如果Widget使用了InheritedWidget的数据,并且在InheritedWidget的数据发生变化时,Flutter Framework层就会触发didChangeDependencies的回调,关于InheritedWidget知识这篇博文最后会详解,这里就不在赘述。
(3)build
build方法在执行完didChangeDependencies和didUpdateWidget之后被执行,每当调用setState(…)方法时都会执行它。
(4)dispose
dispose方法在组件被销毁时调用,一般执行initState初始化的动作时,dispose都有对应的销毁动作。
Widget的唯一身份标识:key
在Flutter里,每一个Widget都具有唯一标识,并且这个唯一标识时在Flutter Framework层创建和渲染时生成的,它就是key。如果key作为参数被传入Widget里面,则会根据指定的名字生成key。
在有些场景下,你需要保存key,并且通过key访问该Widget。这时,可以通过GlobalKey,LocalKey,UniqueKey或ObjectKey进行保存。例如,通过GlobalKey保存key并且在整个应用程序中共享,对应的代码 如下所示:
GlobalKey myKey=new GlobalKey(); @override Widget build(BuildContext context){ return new MyWidget(key:myKey); }
InheritedWidget
InheritedWidget是一个比较特殊的组件,它被定义为父节点。被InheritedWidget暴露出来的数据,可以高效地在Widget树中从上往下传递共享,并支持跨级数据传递。用一张图表示InheritedWidget,如下图所示:
比如在购物车应用中,每当我们添加商品到购物车的时候,InheritedWidget就会被重新创建,状态管理就介绍到这里,下一篇博文将介绍Flutter包管理。