将数据发送到Flutter中的父Widget

Tus*_*Pol 16 dart flutter

我正在尝试将子窗口小部件中的文本设置为父窗口小部件.但是文本没有反映在父窗口小部件中.

试图使用setState()但仍然无法获得预期的结果.

以下是我的代码:

void main() => runApp(new TestApp());

class TestApp extends StatefulWidget {
  @override
  _TestState createState() => new _TestState();
}

class _TestState extends State<TestApp>{

  String abc = "";

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        body: new Column(
          children: <Widget>[
            new Text("This is text $abc"),
            TestApp2(abc)
          ],
        ),
      ),
    );
  }
}


class TestApp2 extends StatefulWidget {

  String abc;

  TestApp2(this.abc);

  @override
  _TestState2 createState() => new _TestState2();
}

class _TestState2 extends State<TestApp2>{
  @override
  Widget build(BuildContext context) {
    return new Container(
      width: 150.0,
      height: 30.0,
      margin: EdgeInsets.only(top: 50.0),
      child: new FlatButton(
          onPressed: (){
            setState(() {
              widget.abc = "RANDON TEXT";
            });
          },
        child: new Text("BUTTON"),
        color: Colors.red,
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?

Din*_*ian 33

在您的示例中,做了一些假设.我会尽力逐一删除.

  1. abc从父级传递给子级,并且您在按下按钮时突变了子级值.由于原始类型在dart中按值传递,因此abc在child 中的值的更改不会更改parent的值abc.请参阅以下代码段.

    void main() {
      String abc = "newValue";
      changeIt(abc);
      print(abc); // newValue
    }
    
    void changeIt(String abc) {
      abc = "newValue";
      print(abc); //newValue
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 让我们假设第一个是错误的(为了理解目的).然后更改abcchild中的值将更改abc父级的值.但是,如果setState不在父母内部调用,父母将不会反映这一变化.在您的情况下,如果您更改下面的代码,它将在单击时单独更改按钮文本(因为调用child的setState).

    new FlatButton(
        onPressed: (){
        setState(() {
            widget.abc = "RANDON TEXT";
        });
        },
        child: new Text(widget.abc), // setting the text based on abc
        color: Colors.red,
    )
    
    Run Code Online (Sandbox Code Playgroud)
  3. 而不是使用的globalState,这将是非常难以维持/调试为应用程序的增长,我会建议使用callbacks.请参考以下代码.

    void main() => runApp(new TestApp());
    
    class TestApp extends StatefulWidget {
    @override
    _TestState createState() => new _TestState();
    }
    
    class _TestState extends State<TestApp>{
    
    String abc = "bb";
    
    callback(newAbc) {
        setState(() {
        abc = newAbc;
        });
    }
    
    @override
    Widget build(BuildContext context) {
        var column = new Column(
            children: <Widget>[
                new Text("This is text $abc"),
                TestApp2(abc, callback)
            ],
            );
        return new MaterialApp(
        home: new Scaffold(
            body: new Padding(padding: EdgeInsets.all(30.0),child: column),
        ),
        );
    }
    }
    
    class TestApp2 extends StatefulWidget {
    
    String abc;
    Function(String) callback;
    
    TestApp2(this.abc, this.callback);
    
    @override
    _TestState2 createState() => new _TestState2();
    }
    
    class _TestState2 extends State<TestApp2>{
    @override
    Widget build(BuildContext context) {
        return new Container(
        width: 150.0,
        height: 30.0,
        margin: EdgeInsets.only(top: 50.0),
        child: new FlatButton(
            onPressed: (){
                widget.callback("RANDON TEXT"); //call to parent
            },
            child: new Text(widget.abc),
            color: Colors.red,
        ),
        );
    }
    }
    
    Run Code Online (Sandbox Code Playgroud)


sal*_*ler 6

您缺少的一点是您的setState方法调用。您调用TestState2.

为了解决这个问题,有两种方法。

第一种方法是创建一个 GlobalKey( https://docs.flutter.io/flutter/widgets/GlobalKey-class.html ) 并将其作为参数传递给子小部件。

第二种方法是为父状态创建一个全局变量,并在子状态中使用它。

我用第二种方法修改了下面的代码。

_TestState _globalState = new _TestState();

class TestApp extends StatefulWidget {
  @override
  _TestState createState() => _globalState;
}

class _TestState extends State<TestApp>{

  String abc = "";

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        body: new Column(
          children: <Widget>[
            new Text("This is text $abc"),
            TestApp2()
          ],
        ),
      ),
    );
  }
}


class TestApp2 extends StatefulWidget {

  TestApp2();

  @override
  _TestState2 createState() => new _TestState2();
}

class _TestState2 extends State<TestApp2>{
  @override
  Widget build(BuildContext context) {
    return new Container(
      width: 150.0,
      height: 30.0,
      margin: EdgeInsets.only(top: 50.0),
      child: new FlatButton(
        onPressed: (){
          _globalState.setState((){
            _globalState.abc = "Button clicked";
          });
        },
        child: new Text("BUTTON"),
        color: Colors.red,
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


Muh*_*fay 5

写出非常准确的答案。只需像上面的答案一样使用回调就可以使用它。 所以你想从另一个 function/widget/class 调用 ParentScreen 的状态。只需按照此代码

import 'package:showErrorMessage.dart';

class ParentScreen extends StatefulWidget {
  ParentScreen({Key key}) : super(key: key);

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

class _ParentScreenState extends State<ParentScreen> {

   callback() {
    setState(() {});
  }
  
  @override
  Widget build(BuildContext context) {
    String message = "hello";
    return Container(
       child: showErrorMessage(message, callback);,
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

这是子部件/功能/类

import 'package:flutter/material.dart';


    showErrorMessage(message, Function callback) {
      return Center(
      child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      Text(
        message,
        style: TextStyle(color: Colors.white, fontSize: 16),
      ),
      GestureDetector(
          onTap: () {
            callback();  // ------ this will change/rebuild the state of its parent class
          },
          child: Icon(
            Icons.refresh,
            size: 30,
            color: Colors.white,
          )),
    ],
  ));
}
Run Code Online (Sandbox Code Playgroud)