【问题标题】:How to change a State of a StatefulWidget inside a StatelessWidget?如何在 StatelessWidget 中更改 StatefulWidget 的状态?
【发布时间】:2019-03-26 14:21:46
【问题描述】:

只是测试颤振。下面的代码示例是一个非常简单的颤振应用程序。问题是我不知道如何调用 TestTextState 类中的 setState() 函数,以便在每次按下更改按钮时更改文本。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Test app',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Test"),
        ),
        body: new Test(),
      ),
    );
  }
}

class Test extends StatelessWidget {

  final TestText testText = new TestText();

  void change() {
    testText.text == "original" ? testText.set("changed") : testText.set("original");
  }

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: [
        testText,
        new RaisedButton(
            child: new Text("change"),
            onPressed: () => change(),
        ),
      ]
    );
  }
}

class TestText extends StatefulWidget {

  String text = "original";

  void set(String str) {
    this.text = str;
  }

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

class TestTextState extends State<TestText> {

  @override
  Widget build(BuildContext context) {
    return new Text(this.widget.text);
  }
}

【问题讨论】:

    标签: dart widget flutter state statefulwidget


    【解决方案1】:

    我通过将 _TestTextState 初始化为 TestText 小部件的最终属性来解决这个问题,它允许在按下更改按钮时简单地更新状态。这似乎是一个简单的解决方案,但我不确定这是否是一个好习惯。

    import 'package:flutter/material.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Test app',
          home: new Scaffold(
            appBar: new AppBar(
              title: new Text("Test"),
            ),
            body: new Test(),
          ),
        );
      }
    }
    
    class Test extends StatelessWidget {
    
      final _TestText text = new _TestText();
    
      @override
      Widget build(BuildContext context) {
        return new Column(
            children: [
              text,
              new RaisedButton(
                child: new Text("change"),
                onPressed: () => text.update(),
              ),
            ]
        );
      }
    }
    
    class TestText extends StatefulWidget {
    
      final _TestTextState state = new _TestTextState();
    
      void update() {
        state.change();
      }
    
      @override
      _TestTextState createState() => state;
    }
    
    class _TestTextState extends State<TestText> {
    
      String text = "original";
    
      void change() {
        setState(() {
          this.text = this.text == "original" ? "changed" : "original";
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return new Text(this.text);
      }
    }
    

    【讨论】:

      【解决方案2】:

      基于您现有代码的解决方案

      class Test extends StatelessWidget {
        final StreamController<String> streamController = StreamController<String>.broadcast();
      
        @override
        Widget build(BuildContext context) {
          final TestText testText = TestText(streamController.stream);
          return new Column(children: [
            testText,
            new RaisedButton(
              child: Text("change"),
              onPressed: () {
                String text = testText.text == "original" ? "changed" : "original";
                streamController.add(text);
              },
            ),
          ]);
        }
      }
      
      class TestText extends StatefulWidget {
        TestText(this.stream);
        final Stream<String> stream;
        String text = "original";
      
        @override
        TestTextState createState() => new TestTextState();
      }
      
      class TestTextState extends State<TestText> {
        @override
        void initState() {
          widget.stream.listen((str) {
            setState(() {
              widget.text = str;
            });
          });
          super.initState();
        }
        @override
        Widget build(BuildContext context) {
          return Text(widget.text);
        }
      }
      

      但这不是最好的主意 - 在 Stateful Widget 中使用 non-final 字段

      附: 你也可以使用这个——scoped_model

      【讨论】:

      • 感谢您的超快速响应。添加 StreamController 似乎是个好主意。没有非最终字段的解决方案会是什么样子?这甚至可能吗?
      • 将此字段存储在TestTextState 中,并在listen 中检查text 的当前值- 例如。在这种情况下,您可以将任何数据发送到流 - 类型无关紧要
      【解决方案3】:

      他们是没有办法这样做的。您必须如何将 StatelessWidget 转换为 StatefulWidget

      【讨论】:

      • 感谢您的重播。因此,如果我的应用程序中有多个不同的页面并且所有页面都共享一个动态文本小部件,这是否意味着我必须将所有屏幕转换为 StatefulWidgets?它将如何反映性能?
      猜你喜欢
      • 2020-05-12
      • 2021-05-16
      • 2021-12-14
      • 2021-07-01
      • 2018-07-06
      • 2020-04-06
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      相关资源
      最近更新 更多