将数据发送到Flutter中的父窗口小部件

时间:2018-07-22 09:51:01

标签: 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,
      ),
    );
  }
}

我想念什么吗?

3 个答案:

答案 0 :(得分:16)

在您的示例中,进行了一些假设。我将尝试一一删除。

  1. 您将abc从父级传递给了子级,然后按了on键,更改了子级值。由于在dart中原始类型是按值传递,因此子级abc的值更改不会更改父级abc的值。请参考以下代码段。

    void main() {
      String abc = "newValue";
      changeIt(abc);
      print(abc); // newValue
    }
    
    void changeIt(String abc) {
      abc = "newValue";
      print(abc); //newValue
    }
    
  2. 让我们假设第一个是错误的(出于理解目的)。然后,在子级中更改abc的值将在父级中更改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,
    )
    
  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,
        ),
        );
    }
    }
    

答案 1 :(得分:3)

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

要解决此问题,有两种方法。

第一种方法是创建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,
      ),
    );
  }
}

答案 2 :(得分:3)

写出非常准确的答案。像上面的答案一样使用回拨即可。 因此您想从另一个函数/小部件/类中调用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);,
    );
  }
}

这是子窗口小部件/函数/类

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