【问题标题】:Can a StatelessWidget contain member variables?StatelessWidget 可以包含成员变量吗?
【发布时间】:2020-10-26 07:14:06
【问题描述】:

我有一个StatelessWidget,它使用ScopedModel 来存储其数据。该小部件基本上显示了一个复选框列表和一些按钮来保存复选框的状态。

现在我想跟踪用户是否更改了任何复选框,即自显示小部件以来选中/取消选中它们。所以我添加了这样的内容:

class MyCheckboxScreen extends StatelessWidget{

    bool _hasBeenModified = false;

    void _itemCheckedChange(bool checked, MyModel model){
        _hasBeenModified = true;

        // Code to change the model here
    }


    void _onCloseButton(){
        if( _hasBeenModified ){
            // Show a warning that there are modifications that will not be be saved
        }
    }


    void _onSaveButton(Context context, MyModel model){
        model.save();
        Navigator.of(context).pop();
    }

}

这似乎可行,但我的 StatelessWidget 现在包含它自己的状态。

该状态不用于更新 UI 和重绘任何内容,它仅用于检查按下“关闭”按钮时是否对任何复选框进行了修改。

StatelessWidget 拥有这种内部状态是否安全?或者这可能是一个问题?例如,widget 是否会意外重新创建,内部状态会丢失?

我觉得the documentation 不是很清楚,它只是说

对于可以动态变化的组合,例如由于具有内部时钟驱动状态,或者取决于某些系统状态,请考虑使用 StatefulWidget。

但这听起来好像只适用于影响 UI 并需要重建小部件的状态。

【问题讨论】:

    标签: flutter flutter-widget flutter-state statelesswidget


    【解决方案1】:

    是的,StatelessWidget 可以有可变变量(您的代码可以编译),但这是错误的。

    需要可变状态的小部件

    这取自documentation。即使您有一个非最终变量,也意味着您的小部件中实际上可以更改某些内容。它不是一个不可变的类。理想情况下,您应该像这样使用StatelessWidgets:

    class MyWidget extends StatelessWidget {
      final int a;
      final String b;
      const MyWidget(this.a, this.b);
    }
    

    或类似的东西,例如

    class MyWidget extends StatelessWidget {
      const MyWidget();
    }
    

    如果您有非最终变量,请使用StatefulWidget。你的班级必须明确是StatefulWidget

    // This is not final. It can be changed (and you will change it)
    // so using the stateless way is wrong
    bool _hasBeenModified = false;
    
    void _itemCheckedChange(bool checked, MyModel model){
      _hasBeenModified = true;
    }
    

    UI 实际上并不重要,因为这里是变量和可变性的问题。有些事情正在发生变化 (bool _hasBeenModified),所以它不能是 StatelessWidget,因为它必须用于所有状态为不可变的情况。

    【讨论】:

      【解决方案2】:

      您有什么不使用有状态小部件的原因吗?无状态小部件不打算以这种方式使用..而且没有任何好处,我不明白你为什么让事情过于复杂..

      【讨论】:

      • 不是真的,唯一的原因是现有屏幕是一个StatelessWidget,我只需要在关闭它之前添加额外的检查。给出答案,我会将其更改为 StatefulWidget!谢谢。
      猜你喜欢
      • 2011-02-11
      • 2011-08-07
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      • 2011-06-16
      • 2011-07-14
      • 1970-01-01
      相关资源
      最近更新 更多