Flutter

flutter Sate 通过widget.xxx 获取Stat

2021-01-28  本文已影响0人  HawkFlying

Sate获取StatefulWidget参数值常见的两种方式

1、StatefulWidget传参给State,在Sate直接使用StatefulWidget传来的参数值,如下:

class TestStatefulWidget extends StatefulWidget {
  //参数 
  final String _xxx;

  TestStatefulWidget(this._xxx);

  @override
  _TestStatefulWidgetState createState() => _TestStatefulWidgetState(this._xxx);
}

class _TestStatefulWidgetState extends State<TestStatefulWidget> {
  final _xxx;

  _TestStatefulWidgetState(this._xxx);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text(_xxx), //直接使用StatefulWidget传来的参数值
    );
  }
}

2、StatefulWidget不传参给State,在Sate通过widget.xxx获取StatefulWidget的参数值,如下:

class TestStatefulWidget extends StatefulWidget {
  //参数
  final String _xxx;

  TestStatefulWidget(this._xxx);

  @override
  _TestStatefulWidgetState createState() => _TestStatefulWidgetState();
}

class _TestStatefulWidgetState extends State<TestStatefulWidget> {
  _TestStatefulWidgetState();

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text(widget._xxx), //通过widget获取StatefulWidget参数值
    );
  }
}

Sate通过widget.xxx获取StatefulWidget参数值之坑

上面两种获取参值方式的差别在于StatefulWidget有没有将参数直接传给State,Sate是否通过widget.xxx获取StatefulWidget参数值;
下面通过实例来演示这两种获取参数值的差别,如下:

class StatefulWidgetParamPage extends StatefulWidget {
  final String title;

  StatefulWidgetParamPage({Key key, this.title}) : super(key: key);

  @override
  _StatefulWidgetParamPageState createState() =>
      _StatefulWidgetParamPageState();
}

class _StatefulWidgetParamPageState extends State<StatefulWidgetParamPage> {
  int i;

  @override
  void initState() {
    super.initState();
    i = 0;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
          alignment: Alignment.center,
          width: double.infinity,
          height: double.infinity,
          child: Column(
            children: <Widget>[
              TestWidgetA(
                  TestModel(
                    'WidgetA参数:',
                  ),
                  i.toString()),
              TestWidgetB(TestModel('WidgetB参数:'), i.toString()),
              RaisedButton(
                  onPressed: () {
                    i++;
                    setState(() {});
                  },
                  child: Text('值增加刷新')),
              RaisedButton(
                  onPressed: () {
                    i++;
                  },
                  child: Text('值增加不刷新')),
              RaisedButton(
                  onPressed: () {
                    setState(() {});
                  },
                  child: Text('只刷新')),
            ],
          )),
    );
  }
}

class TestModel {
  String title;
  dynamic value;

  TestModel(
    this.title,
  ) {
    var r = new Random();
    value = r.nextInt(1000); //用于区分对象是否有重新创建,对象重新创建,值会变化
  }

  @override
  String toString() {
    return '$title  自定义对象${value ?? ''}';
  }
}

class TestWidgetA extends StatefulWidget {
  final TestModel model;
  final String value;

  TestWidgetA(this.model, this.value);

  @override
  _TestWidgetAState createState() => _TestWidgetAState();
}

class _TestWidgetAState extends State<TestWidgetA> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Container(
        alignment: Alignment.center,
        child: Text(
            '${widget?.model?.toString()}    change value=${widget?.value}\ncontext=$context\n'), //展示传参数据 值随刷新变
      ),
      onTap: () {
        print(
            '${widget?.model?.toString()}    change value=${widget?.value}\ncontext=$context\n'); //值不变,刷新后widget重新创建,值才变
        /*setState(() {//内部刷新

        });*/
      },
    );
  }
}

class TestWidgetB extends StatefulWidget {
  final TestModel model;
  final String value;

  TestWidgetB(this.model, this.value);

  @override
  _TestWidgetBState createState() => _TestWidgetBState(this.model, this.value);
}

class _TestWidgetBState extends State<TestWidgetB> {
  final TestModel model;
  final String value;

  _TestWidgetBState(this.model, this.value);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Container(
        alignment: Alignment.center,
        child: Text(
            '${model?.toString()}    change value=$value\ncontext=$context\n'), //展示传参数据  值不随刷新变
      ),
      onTap: () {
        print(
            '${model?.toString()}    change value=$value\ncontext=$context\n'); //值不随刷新变
        /*setState(() {//内部刷新

        });*/
      },
    );
  }
}

上面代码比较多,可以先不看,先看下面的实例效果或自行跑demo,不懂再来看代码和代码说明
代码说明:

外部计数值增加增加并刷新界面效果:

外部计数值增加并刷新界面效果.gif
效果说明:

外部计数值增加不刷新界面效果:

外部计数值增加不刷新界面效果.gif
效果说明:

只刷新界面效果:

只刷新界面效果.gif
效果说明:

不刷新,连续点击获取实时参数值效果:

连续点击获取实时参数值效果.png
效果说明:

内部刷新,连续点击获取实时参数值效果:

内部刷新,连续点击获取实时参数值效果.png
效果说明:

总结

StatefulWidget传参给State,在Sate直接使用StatefulWidget传来的参数值:

StatefulWidget不传参给State,在Sate通过widget.xxx获取StatefulWidget传来的参数值:

原因分析

1、外部界面刷新:

2、StatefulWidget内部刷新:

温馨提示:源码里大多都是通过widget.xxx来获取StatefulWidget参数值,所以并不是说widget.xxx不可取,这两种方式各有优劣势,用哪一种根据自己的业务进行取舍,文章主要是为了说明Sate 通过widget.xxx 获取StatefulWidget参数值需要注意参数值可能随外部环境变化而会变化。

demo传送门

上一篇 下一篇

猜你喜欢

热点阅读