简体   繁体   English

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

[英]How does the stateful vs. stateless distinction affect when widgets will be rebuilt?

I am trying to understand how state and lifting state works in Flutter.我想了解状态和提升状态在 Flutter 中是如何工作的。 In the code below I made a simple app where I tried to pass or lift a string and a function through multiple levels.在下面的代码中,我制作了一个简单的应用程序,我试图通过多个级别传递或提升一个字符串和一个函数。

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),
      ],
    );
  }
}

When the app starts, the string data in the _MyAppState state class is passed to the MainApp StatelessWidget when MainApp is built.当应用程序启动时, _MyAppState状态类中的字符串data会在构建MainApp时传递给MainApp StatelessWidget。 In a similar manner, info is passed then to Level2 StatelessWidget and Level3 StatefulWidget.然后以类似的方式将信息传递给Level2 StatelessWidget 和Level3 StatefulWidget。

When the TextField in Level3 changes, setTextField is triggered.Level3中的TextField发生变化时,触发setTextField setTextField is defined up in MyApp and I figured that when the String data changes (inside setState() ) it should trigger rebuilding of all the widgets affected by the change. setTextField是在MyApp中定义的,我认为当 String data发生变化时(在setState()内部)它应该触发重建所有受变化影响的小部件。

The text in the MainApp widget (appBar) changes, showing MainApp was rebuilt as I expected. MainApp小部件 (appBar) 中的文本发生变化,显示MainApp已按预期重建。 But nothing happens to the Level3 widget;但是Level3小部件没有任何反应; it's not rebuilt.它没有重建。 The print statement in the createState() method does not execute, and the Text widget's text does not change. createState()方法中的 print 语句不执行,Text 小部件的文本不改变。

Why doesn't the Level3 StatefulWidget rebuild?为什么Level3 StatefulWidget 不重建?

In my understanding, the stateful widget Level3 is already created at the given location in the tree.据我所知,有状态的小部件 Level3 已经在树中的给定位置创建。 And according to the contract of the stateful widget , It is the responsibility of the widget implementer to ensure that the State is promptly notified when such state changes, using State.setState.并且根据有状态小部件的契约,小部件实现者有责任确保在此类状态更改时及时通知 State,使用 State.setState。 So in your case you need to have setstate in level3 to be notified of the change again.因此,在您的情况下,您需要在 level3 中设置 setstate 才能再次收到更改通知。 The rebuilding only happens at level 1 because setState is called.重建只发生在级别 1,因为调用了 setState。

The rebuilding process continues recursively until the description of the user interface is fully concrete.重建过程递归地继续,直到用户界面的描述完全具体。 In Level 3, the class has its own set of fields String level3Data;在级别 3 中,该类有自己的一组字段 String level3Data; Function setTextField;函数设置文本字段; It means these need to be again set using SetState or if you do something like this then the widget building continues.这意味着这些需要使用 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),
      ],
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM