【问题标题】:Flutter - Why is child widget's initState() is not called on every rebuild of Parent widget?Flutter - 为什么每次重建父小部件时都不调用子小部件的 initState()?
【发布时间】:2019-07-12 14:00:00
【问题描述】:

我有一个Parent 小部件,它保存一些状态,在这种情况下是一个计数器。

此状态通过 Child 小部件的构造函数传递给它。

现在,我的理解是,Child 应该在每次Parent 的状态更改时重新构建,因为它在Parentbuild() 函数内,并且build() 每次都会被调用- 状态变化的时间。

这个概念让我相信每次计数器更改时都会打印INIT STATE! 消息。但事实并非如此!

我本质上想要一个“钩子”,只要Child 的构造函数参数 (message) 发生变化,就会触发一次。

有人能解释一下为什么会这样吗,有上述“钩子”的正确方法是什么?

class Child extends StatefulWidget {
  final String message;

  const Child(this.message, {Key key}) : super(key: key);

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

class _ChildState extends State<Child> {
  @override
  void initState() {
    print("INIT STATE!");
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(widget.message),
    );
  }
}

class Parent extends StatefulWidget {
  @override
  _ParentState createState() => _ParentState();
}

class _ParentState extends State<Parent> {
  int _counter = 0;

  @override
  void initState() {
    Timer.periodic(Duration(seconds: 1), (_) {
      if (mounted) {
        setState(() {
          _counter += 1;
        });
      }
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Child(_counter.toString());
  }
}

【问题讨论】:

标签: dart flutter


【解决方案1】:

好的,看起来State 类的文档中明确提到了这一点。

正确的做法是重写State子类中的didUpdateWidget方法。

【讨论】:

    【解决方案2】:

    感谢@Dev Aggarwal。

    延伸到 Dev Aggarwal 的回答,我在这里包含了示例。

    在 Child 小部件中实现 didUpdateWidget() 方法。当父状态改变时,didUpdateWidget() 方法将调用子部件。

    Implement didUpdateWidget() method in Child widget.
    
    @override
      void didUpdateWidget(<YourChildScreen> oldWidget) {
    
        super.didUpdateWidget(oldWidget);
    
        print("oldWidget.searchTerm is ${oldWidget.searchTerm}");
        print("widget.searchTerm is ${widget.searchTerm}");
    
        if (oldWidget.searchTerm != widget.searchTerm) {
    
          this.updateChildWithParent();
    
        }
      }
    
    
    void updateChildWithParent() {
        print("updateChildWithParent/search screen");
        setState(() {
    
          _mJsonLoaded = false; // For loader
          if (listArray.length > 0) {
            listArray.clear();
          }
        });
    
        // Do whatever you want here…
        // Like call api call again in child widget.
      }
    

    希望对你有用。

    【讨论】:

    【解决方案3】:

    initState 仅在状态第一次插入小部件树时调用。稍后,处理后续调用的是didUpdateWidget

    【讨论】:

      猜你喜欢
      • 2020-07-25
      • 2021-08-08
      • 2021-02-17
      • 1970-01-01
      • 2020-12-22
      • 2021-05-04
      • 2019-01-14
      • 1970-01-01
      • 2021-04-27
      相关资源
      最近更新 更多