【问题标题】:Flutter accessing State class variable of StatefulWidget from a different classFlutter 从不同的类访问 StatefulWidget 的 State 类变量
【发布时间】:2021-02-19 23:32:40
【问题描述】:

我有一个 StatefulWidget 类“FirstClass”,它扩展了一个状态“_FirstClassState”。从一个名为“_SecondClassState”的单独 State 类中,我试图访问一个变量的值(在“_FirstClassState”中称为“计数器”)。

我找到了解决方案,但我不确定这是否是解决问题的最佳方法。我试过查看其他类似的问题:

  • How to access Stateful widget variable inside State class outside the build method?(在 StatefulWidget 类中声明变量并在 State 类中使用 'widget.' 不允许我从 '_SecondClassState' 中获取 'counter' 的值)
  • 我还看到其他网站推荐使用 GlobalKey。然而,即使这可能是一个解决方案,我也没有进一步探索,因为我发现其他网站建议尽量减少 GlobalKeys 的使用

second_class.dart:

import 'package:brew_crew/question/first_class.dart';
import 'package:flutter/material.dart';

class SecondClass extends StatefulWidget {
  @override
  _SecondClassState createState() => _SecondClassState();
}

class _SecondClassState extends State<SecondClass> {
  final FirstClass firstClass = FirstClass();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("MyApp"),
        centerTitle: true,
      ),
      body: Column(
        children: <Widget>[
          firstClass, //Displays the button to increase 'counter'
          FlatButton(
              child: Text("Submit"),
              onPressed: () {
                print(firstClass
                    .getCounter()); //I need to get the value of 'counter' here to use elsewhere
              }),
        ],
      ),
    );
  }
}

first_class.dart

import 'package:flutter/material.dart';

class FirstClass extends StatefulWidget {
  final _FirstClassState firstClassState = _FirstClassState();

  @override
  _FirstClassState createState() => firstClassState;

  int getCounter() {
    return firstClassState.counter;
  }
}

class _FirstClassState extends State<FirstClass> {
  int counter = 0;

  //Increases counter by 1
  void _increaseCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    //A button which increases counter when clicked
    return FlatButton.icon(
      icon: Icon(Icons.add),
      label: Text("Counter: $counter"),
      onPressed: () {
        _increaseCounter();
      },
    );
  }
}

如您所见,在“FirstClass”中,我初始化了一个“_FirstClassState”的新实例。在 'getCounter()' 函数中使用它,我可以得到 'counter' 值。

有没有比这更好的方法(例如最佳实践、更少的代码行、更容易理解的方法等)来实现我想要做的事情?

【问题讨论】:

  • 您的 FirstClass 和 SecondClass 的结构如何? SecondClass 在小部件树中位于 FirstClass 之下还是之上,还是它们是兄弟?
  • @AshutoshSingh 对不起,我是 Flutter 的新手,如果没有回答,我深表歉意。我首先加载“SecondClass”小部件,然后在“SecondClass”小部件中加载“FirstClass”小部件。所以我认为'SecondClass'将是'FirstClass'的父级

标签: flutter statefulwidget


【解决方案1】:

如果您绝对必须从外部访问小部件的状态,则绝对推荐使用GlobalKey 的方法。但是,在这种情况下,您不应该使用任何一种方法。

_SecondClassState 应该包含counter,并且您应该将它与increaseCounter 函数一起作为参数传递给FirstClass。如果要增加数字,只需调用该函数即可。

类似的东西:

class SecondClass extends StatefulWidget {
  @override
  _SecondClassState createState() => _SecondClassState();
}

class _SecondClassState extends State<SecondClass> {
  int counter = 0;

  //Increases counter by 1
  void _increaseCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("MyApp"),
        centerTitle: true,
      ),
      body: Column(
        children: <Widget>[
          FirstClass(counter: counter, increaseCounter: _increaseCounter), //Displays the button to increase 'counter'
          FlatButton(
              child: Text("Submit"),
              onPressed: () {
                print(counter.toString()); //I need to get the value of 'counter' here to use elsewhere
              }),
        ],
      ),
    );
  }
}
class FirstClass extends StatefulWidget {
  final int counter;
  final Function increaseCounter;

  FirstClass({this.counter, this.increaseCounter});

  final _FirstClassState firstClassState = _FirstClassState();

  @override
  _FirstClassState createState() => firstClassState;
}

class _FirstClassState extends State<FirstClass> {
  @override
  Widget build(BuildContext context) {
    //A button which increases counter when clicked
    return FlatButton.icon(
      icon: Icon(Icons.add),
      label: Text("Counter: ${widget.counter}"),
      onPressed: () {
        widget.increaseCounter();
      },
    );
  }
}

【讨论】:

  • 感谢您的回答。我试过实现这个,但我收到以下错误:'方法“调用”在 null 上被调用。接收方:null 尝试调用:call()'。函数“increaseCounter()”在“FirstClass”构造函数中作为“null”传递(但“counter”的值正确传递)。你知道为什么会这样吗?
  • @SidharthRanjith 不确定。尝试重新启动调试过程,上面的代码对我有用。
  • 发现错误。我将'increaseCounter()'而不是'increaseCounter'作为参数之一传递给'FirstClass'。感谢您对此的帮助。出于兴趣,您能否告诉我为什么这被认为比我在问题中使用的词更好?
  • @SidharthRanjith 啊,可以理解为什么那不起作用。好吧,一般来说,数据“向下”流动,从父小部件流向子小部件。如果您没有非常充分的理由从外部访问小部件的状态,那么您不应该这样做,因为它是反模式。 Here's a good read about where state should be managed.
猜你喜欢
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 2021-02-27
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 2021-05-16
相关资源
最近更新 更多