如何在Flutter中从子Widget更新父Widget的状态并更新子Widget的状态?

8

我希望你能帮忙翻译以下内容,谢谢。

下面的示例代码旨在从子组件更新父组件的状态,同时也更新子组件的状态。父组件的文本值将会更新,同时也会改变子组件按钮的颜色。

import 'package:flutter/material.dart';

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

class AppIndex extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: ParentWidget());
  }
}

class ParentWidget extends StatefulWidget {
  @override
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  String _textValue = 'Old Value';

callback(newValue){
  setState(() {
    _textValue = newValue;
  });
}

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Text(_textValue),
        ChildWidget(),
      ],
    );
  }
}

class ChildWidget extends StatefulWidget {
  String textValue;
  Function callback;

  ChildWidget({this.textValue, this.callback});

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

class _ChildWidgetState extends State<ChildWidget> {
  bool buttonState = false;

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      color: buttonState == true ? Colors.greenAccent : Colors.redAccent,
      child: Text('Update State'),
      onPressed: () {
        setState(() {
          if (buttonState == false) {
            buttonState = true;
          } else if (buttonState == true) {
            buttonState = false;
          }
        });

        widget.callback('New Value');
      },
    );
  }
}

到目前为止,这个程序可以更新子小部件的颜色/状态,但是父小部件似乎没有更新其状态。我的原始代码只更新了父级的状态,而不是父级和子级(相同的概念和关注点)。上面的示例代码是在我提问之前进行初始研究的结果。
我认为我的代码结构有问题,或者根据我的制作方式,Flutter架构中不可能实现这一点。如果可能的话,您能否为我推荐具有相同行为的解决方案?(更新父级和子级状态)
抱歉,我对这种类型的编程和架构还很陌生。
1个回答

13

欢迎使用Flutter!看起来您没有将回调传递给子部件。在实例化ChildWidget时,您应该这样做:new ChildWidget(callback: this.callback);然后,您可以通过StatefulWidgetwidget属性从State<ChildWidget>类中访问值,例如:widget.callback

另外,值得注意的是,您应该尽量避免使用Function类型,因为它实际上并没有提供有关函数将返回什么或将接受哪些参数的信息。为此,Dart使用typedef 关键字。例如,对于需要将日期字符串转换为日期并返回日期的函数(虽然Dart具有出色的内置日期支持,但这是一个有点牵强的例子),您可以执行以下操作:

typedef Date StringToDateParser(String datestring);

然后,在您的类中,您可以将StringToDateParser用作类型。

import 'package:flutter/material.dart';

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

class AppIndex extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: ParentWidget());
  }
}

class ParentWidget extends StatefulWidget {
  @override
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  String _textValue = 'Old Value';

  callback(newValue){
    setState(() {
      _textValue = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Text(_textValue),
        ChildWidget(callback: this.callback, this._text),
      ],
    );
  }
}

class ChildWidget extends StatefulWidget {

  Function callback;

  ChildWidget({this.textValue, this.callback});

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

class _ChildWidgetState extends State<ChildWidget> {
  bool buttonState = false;

  _ChildWidgetState();

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      color: buttonState == true ? Colors.greenAccent : Colors.redAccent,
      child: Text('Update State'),
      onPressed: () {
        setState(() {
          if (buttonState == false) {
            buttonState = true;
          } else if (buttonState == true) {
            buttonState = false;
          }
        });

        widget.callback('New Value');
      },
    );
  }
}

1
非常感谢!太快了。我现在意识到我的错误,你知道我发誓这个概念在我的实际代码中似乎不起作用。你的建议让我再次审查它(在已经进行了很多查找之后),并发现它可以工作。 - AverageCoder
希望这不是太多,你能更详细地向我解释一下你提到的状态传播吗? :) - AverageCoder
哈哈哈,这就是编程的诅咒,代码在别人看之前永远不会工作,然后哧!神奇地开始工作 :) 祝你好运。Flutters很棒。 - Spencer Stolworthy
当然,让我更新我的答案以包括您的代码和所做的更正。 - Spencer Stolworthy
我已经尝试过了,现在明白你的意思了,但是通过传递回调函数(就像你提到的那样)并通过this.callback()来调用它,与通过widget.callback()来调用它相比,有什么优势吗?我最初学到的是我所写下的内容,也许我可以通过这种方式改进我的代码。 :) - AverageCoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接