uiswitchbutton 点击不改变状态_Flutter 基本状态管理setState的使用实践
Flutter 中的Widget组件分为有状态和无状态两种。由用户操作而带来显示状态变化的都是有状态组件。在编辑器中输入stful、stless关键字,可以快速创建有状态和无状态组件类。比如最常见的Button,用户只是点击按钮提交表单(没有其他样式变化),那么它就是一个无状态组件。而Input输入框(TextField),则是典型的有状态组件,用户输入内容,UI显示对应内容。基础的状态管理对于组
Flutter 中的Widget组件分为有状态和无状态两种。由用户操作而带来显示状态变化的都是有状态组件。
在编辑器中输入stful、stless关键字,可以快速创建有状态和无状态组件类。
比如最常见的Button,用户只是点击按钮提交表单(没有其他样式变化),那么它就是一个无状态组件。
而Input输入框(TextField),则是典型的有状态组件,用户输入内容,UI显示对应内容。
基础的状态管理对于组件的开发是非常简单的,在StatefulWidget组件下的State类中声明变量,在渲染组件中引用这个变量,在需要更新显示内容时,使用setState函数回调中修改变量值,这样UI就会重新渲染。
flutter中的setState函数,和React中的如出一辙,都是更新UI中显示数据的用途。
在文档中所说,当调用setState后,所在Widget会进行重新渲染,这样便实现了页面上显示数据的更新。
下面是一个简单的有状态组件,点击按钮,显示的数字会+1:
...class ClickTest extends StatefulWidget { @override _ClickTestState createState() => _ClickTestState();}class _ClickTestState extends State { int clickTime = 0; @override Widget build(BuildContext context) { return Column( children: [ Text("clickTime: ${clickTime}"), RaisedButton( child: Text("点击"), onPressed: () { clickTime ++; setState(() { // 也可以将状态修改写在这个函数参数里 // clickTime ++; }); }, ) ], ); }}
当点击屏幕中的按钮时,数字就会递增,我们在setState前将变量+1,然后再调用setState一样可以实现页面数字的变化,由此可见并非必须将修改状态写在函数的参数中。如果我们在修改变量的值后不调用setState,那么页面不会有改变。
上面的例子只是修改了简单类型Int,换做其他类型的变量也一样有效,因为重新渲染跟变量类型并没有关系。
疑问
我们知道,在实例化一个组件类时,会渲染类中的build方法所返回的组件。
我猜测setState会重新触发build函数,实现更新显示内容的目的。
为了验证自己的想法,我将设计一个父子组件嵌套的结构,需要的注意的是,在子组件按钮事件中我们并没调用setState,也就是说点击子组件按钮只会使子组件中的变量+1,而页面并不会有任何改变:
再点击父组件按钮,发现子组件的数字更新了,说明了setState会重新渲染当前组件和子组件,整个都进行了重新的build,如果我们在build函数中print,就会发现,在调用setState后,会执行build。
到这里就彻底证实了自己的猜测:setState是靠重新调用build函数进行的页面再渲染,也就是每个组件是靠重新实例化进行的再次渲染。
常见问题:
下方代码中,点击按钮是否会触发页面上的数字变化?
...class XXXState extends State { var click = 0; Widget w; @override void initState() { super.initState(); w = Column( children: [ Text("${click}"), RaisedButton( child: Text("点击"), onPressed: () { click++; setState(() {}); }, ), ], ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: w, ); }}
解答:不会变化,因为w变量中的组件,并没有重新实例化,所有w的状态一直都保持不变,组件一直保存在变量w中。
点击按钮确实会使当前组件重新渲染、会重新调用build,但是其中的子组件w,并没有重新实例化,其中的状态也没有发生任何改变。
更多推荐


所有评论(0)