同一个 Statefulwidget 的多个实例似乎共享同一个 State 对象?

Posted

技术标签:

【中文标题】同一个 Statefulwidget 的多个实例似乎共享同一个 State 对象?【英文标题】:Multiple instances of same Statefulwidget seem to share the same State object? 【发布时间】:2020-10-25 17:29:56 【问题描述】:

我正在尝试使用 Flutter 构建应用程序,但遇到了一个小问题。我正在尝试用三页实现一个 BottomNavigaionBar 风格的应用程序。 (参见第一个 sn-p)布局使用三个“ChorePage”类型的对象。似乎该应用正在创建三个 ChorePage 实例,但只有一个 _ChorePageState 实例。

这会导致变量 _dataRows 在三个选项卡之间共享,这意味着我不能将不同的信息放入不同的选项卡中。为什么会发生这种情况,我该如何预防?

我已将打印语句放入 createState() 函数中,并在每次重建 ChorePage 时调用的 PopulateRows 函数中打印“this”变量。打印输出如下所示,并确认这三个小部件确实使用了相同的 State 对象。 (createState 只对对象 A 调用一次,并且 this 变量指向同一个对象)

class AppLayout extends StatefulWidget 
  @override
  _AppLayoutState createState() => _AppLayoutState();


class _AppLayoutState extends State<AppLayout> 
  int _currentIndex = 0;
  String title = 'Test';

  List<Widget> _children = [
    new ChorePage(Title:'A'),
    new ChorePage(Title:'B'),
    new ChorePage(Title:'C')
  ];

  @override
  Widget build(BuildContext context) 


    //STUFF BEFORE INIT
    return Scaffold(
      appBar: AppBar(
        title: Text('$title'),
      ),
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        onTap: onTabTapped,
        currentIndex: _currentIndex,
        items:[
          BottomNavigationBarItem(
            icon: Icon(MdiIcons.sprayBottle),
            title:Text('Menu1'),
          ),
          BottomNavigationBarItem(
            icon: Icon(MdiIcons.glassMugVariant),
            title:Text('Menu2'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.event_note),
            title:Text('Menu3'),
          )
      ]
      ),
    );
  

  void onTabTapped(int index)
    setState(() 
      _currentIndex = index;
    );
  

杂务页面


class ChorePage extends StatefulWidget 
  final String Title;
  const ChorePage(Key key, this.Title): super(key: key);

  @override
  _ChorePageState createState() 
    print('Creating: '+this.Title);
    return new _ChorePageState();
  


class _ChorePageState extends State<ChorePage> 
  List<DataRow> _dataRows = [];

  @override
  Widget build(BuildContext context) 
    PopulateRows();
    return SingleChildScrollView(
      child:Center(
          child: DataTable(
            columns: [
              DataColumn(label: Text(widget.Title.toString())),
              DataColumn(label: Text('Col1')),
              DataColumn(label: Text('Col2')),
            ],
            rows: _dataRows,
          ),
        ),
    );
  

  void PopulateRows()
    print(this);
    print(widget.Title.toString());

    //_dataRows = [];
    for(int i=0;i<1;i++) 
      DataRow R = DataRow(cells:[]);
      R.cells.add(DataCell(Text(widget.Title)));
      R.cells.add(DataCell(Text(i.toString())));
      R.cells.add(DataCell(Text((i + 1).toString())));
      _dataRows.add(R);
    
  


打印输出:

Installing build\app\outputs\apk\app.apk...
Debug service listening on ws://127.0.0.1:59033/TvJtQ-PN3a8=/ws
Syncing files to device Mi 9T Pro...
I/flutter (28856): Creating: A
I/flutter (28856): _ChorePageState#d1d35
I/flutter (28856): A
I/xxxxxxx.tms_ap(28856): ProcessProfilingInfo new_methods=403 is saved saved_to_disk=1 resolve_classes_delay=8000
I/flutter (28856): _ChorePageState#d1d35
I/flutter (28856): B
I/flutter (28856): _ChorePageState#d1d35
I/flutter (28856): C

【问题讨论】:

【参考方案1】:

今天我认为是同样的问题,解决方案最终是将 String 键传递给 StatefulWidget 构造函数。所以在你的例子中:

  List<Widget> _children = [
    new ChorePage(key: Key('A'), Title:'A'),
    new ChorePage(key: Key('B'), Title:'B'),
    new ChorePage(key: Key('C'), Title:'C')
  ];

【讨论】:

以上是关于同一个 Statefulwidget 的多个实例似乎共享同一个 State 对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何一次运行多个 Spark 2.0 实例(在多个 Jupyter Notebook 中)?

最大似然估计实例 | Fitting a Model by Maximum Likelihood (MLE)

Flutter局部刷新方法

B-概率论-极大似然估计

StatefulWidget

StatefulBuilder 与 StatefulWidget