有状态与无状态的区别如何影响小部件的重建时间?

时间:2019-12-01 21:20:37

标签: flutter statefulwidget

我试图了解状态和提升状态在Flutter中的工作方式。在下面的代码中,我制作了一个简单的应用程序,尝试通过多个级别传递或提升字符串和函数。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String data = 'MyApp class data';

  void setTextField(String s) {
    setState(
      () {
        data = s;
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainApp(data, setTextField),
    );
  }
}

class MainApp extends StatelessWidget {
  final String mainAppData;
  final Function setTextField;
  MainApp(this.mainAppData, this.setTextField);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(mainAppData)),
      body: Container(
        child: Level2(mainAppData, setTextField),
      ),
    );
  }
}

class Level2 extends StatelessWidget {
  final String level2Data;
  final Function setTextField;
  Level2(this.level2Data, this.setTextField);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Level3(level2Data, setTextField),
    );
  }
}

class Level3 extends StatefulWidget {
  final String level3Data;
  final Function setTextField;
  Level3(this.level3Data, this.setTextField);

  @override
  _Level3State createState() {
    print('Level3: $this.level3Data');
    return _Level3State(this.level3Data, this.setTextField);
  }
}

class _Level3State extends State<Level3> {
  String level3Data;
  Function setTextField;
  _Level3State(this.level3Data, this.setTextField);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        TextField(
          onChanged: setTextField,
        ),
        Text(level3Data),
      ],
    );
  }
}

应用启动时,data状态类中的字符串_MyAppState将在构建MainApp时传递给MainApp StatelessWidget。以类似的方式,信息随后传递到Level2 StatelessWidget和Level3 StatefulWidget。

TextField中的Level3发生变化时,setTextField被触发。 setTextField是在MyApp中定义的,我发现当字符串data发生变化(在setState()内部)时,它将触发所有 all 小部件的重建。受更改的影响。

MainApp小部件(appBar)中的文本发生更改,显示MainApp已按照预期重建。但是Level3小部件没有任何反应;它没有重建。 createState()方法中的print语句不会执行,并且Text小部件的文本不会更改。

为什么Level3 StatefulWidget不重建?

1 个答案:

答案 0 :(得分:0)

据我了解,有状态小部件Level3已在树中的给定位置创建。 根据{{​​3}}的合同, 小部件实现者有责任使用State.setState确保在状态发生变化时及时通知该状态。 因此,在您的情况下,您需要在level3中具有setstate才能再次收到有关更改的通知。 重建仅在级别1发生,因为setState被调用。

重建过程将以递归方式继续进行,直到对用户界面的描述完全具体为止。 在级别3中,该类具有自己的一组字段  字符串level3Data;  函数setTextField; 这意味着需要使用SetState再次设置它们,或者如果您执行类似的操作,则将继续构建小部件。

class Level3 extends StatefulWidget {
  final String level3Data;
  final Function setTextField;
  Level3(this.level3Data, this.setTextField);

  @override
  _Level3State createState() {
    print('Level3: $this.level3Data');
    return _Level3State();
  }
}

class _Level3State extends State<Level3> {
  // String level3Data;
  // Function setTextField;

  @override
  Widget build(BuildContext _) {
    return Column(
      children: <Widget>[
        TextField(
          onChanged: widget.setTextField,
        ),
        Text(widget.level3Data),
      ],
    );
  }
}