Flutter 字段在 Stateful widget 中不能是最终字段

Chr*_*ris 1 final widget stateful dart flutter

Flutter 正在抱怨 ,_isSelected因为它不是final。问题是这是must not最终的,因为它是在buttonPressed......

class SelectionButton extends StatefulWidget {
  final String title;
  final Function(String) onSelectionButtonTap;
  bool isSelected;

  SelectionButton({
    required this.title,
    required this.onSelectionButtonTap,
    required this.isSelected,
  });
  @override
  _SelectionButtonState createState() => _SelectionButtonState();
}

class _SelectionButtonState extends State<SelectionButton> {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: GestureDetector(
        onTap: () {
          setState(() {
            widget.onSelectionButtonTap(widget.title);
            widget.isSelected = !widget.isSelected;
          });
        },
        child: Container(
          decoration: BoxDecoration(
            color: widget.isSelected ? AppColors.primary : AppColors.white,
            borderRadius: BorderRadius.circular(
              scaleWidth(10),
            ),
          ),
          child: Center(
            child: Text(
              widget.title,
              textAlign: TextAlign.center,
              style: widget.isSelected
                  ? AppTextStyles.h5White
                  : AppTextStyles.h5Light,
            ),
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

这是 Flutter 给我的警告:

此类(或此类继承的类)被标记为“@immutable”,但其一个或多个实例字段不是最终的:SelectionButton.isSelected

正如你所看到的,我正在改变widget.isSelected。我对 Flutter 很陌生,不知道为什么 Flutter 在这里抱怨。一切都按预期进行,但我想这不是最佳实践?我该如何解决这个问题?我在这里缺少什么?

Ale*_*ord 6

这是因为您应该isSelected在 State 类中进行操作,而不是在 StatefulWidget 中。您还希望将Key参数保留在小部件上。将所有变量声明为 Final 允许您将类声明为 const。

在 dart 中,const 意味着对象的整个深层状态可以完全在编译时确定,并且对象将被冻结且完全不可变。

我们希望尽可能使用 const。

以下是重构小部件以关闭 Flutter 编译器的方法:

class SelectionButton extends StatefulWidget {
  final String title;
  final Function(String) onSelectionButtonTap;
  final bool isSelected;

  const SelectionButton({
    Key? key,
    required this.title,
    required this.onSelectionButtonTap,
    required this.isSelected,
  }) : super(key: key);

  @override
  _SelectionButtonState createState() => _SelectionButtonState();
}

class _SelectionButtonState extends State<SelectionButton> {
  bool isSelected = false;

  @override
  void initState() {
    super.initState();
    isSelected = widget.isSelected;
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: GestureDetector(
        onTap: () {
          setState(() {
            widget.onSelectionButtonTap(widget.title);
            isSelected = !isSelected;
          });
        },
        child: Container(
          decoration: BoxDecoration(
            color: isSelected ? AppColors.primary : AppColors.white,
            borderRadius: BorderRadius.circular(
              scaleWidth(10),
            ),
          ),
          child: Center(
            child: Text(
              widget.title,
              textAlign: TextAlign.center,
              style: isSelected
                  ? AppTextStyles.h5White
                  : AppTextStyles.h5Light,
            ),
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)