flutter 基本状态管理setState的使用实践

Flutter 中的Widget组件分为有状态和无状态两种。由用户操作而带来显示状态变化的都是有状态组件。

在编辑器中输入stfulstless关键字,可以快速创建有状态和无状态组件类。

比如最常见的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 ++;
            });
          },
        )
      ],
    );
  }
}

[图片上传失败...(image-fa2080-1596591627125)]

当点击屏幕中的按钮时,数字就会递增,我们在setState前将变量+1,然后再调用setState一样可以实现页面数字的变化,由此可见并非必须将修改状态写在函数的参数中。如果我们在修改变量的值后不调用setState,那么页面不会有改变。

上面的例子只是修改了简单类型Int,换做其他类型的变量也一样有效,因为重新渲染跟变量类型并没有关系。

疑问

我们知道,在实例化一个组件类时,会渲染类中的build方法所返回的组件。

我猜测setState会重新触发build函数,实现更新显示内容的目的。

为了验证自己的想法,我将设计一个父子组件嵌套的结构,需要的注意的是,在子组件按钮事件中我没并没调用setState,也就是说点击子组件按钮只会使子组件中的变量+1,而页面并不会有任何改变:

[图片上传失败...(image-dced64-1596591627126)]

再点击父组件按钮,发现子组件的数字更新了,说明了setState会重新渲染当前组件和子组件,整个都进行了重新的build,如果我们在build函数中print,就会发现,在调用setState后,会执行build。

[图片上传失败...(image-91f681-1596591627126)]

到这里就彻底证实了自己的猜测: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,并没有重新实例化,其中的状态也没有发生任何改变。

你可能感兴趣的:(flutter 基本状态管理setState的使用实践)