在有状态的小部件中,颤振字段不能是最终的

Posted

技术标签:

【中文标题】在有状态的小部件中,颤振字段不能是最终的【英文标题】:Flutter field must not be final in Stateful widget 【发布时间】:2021-07-15 02:33:24 【问题描述】:

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,
            ),
          ),
        ),
      ),
    );
  

这是 Flutter 给我的警告:

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

如您所见,我正在更改widget.isSelected。我对颤振很陌生,不知道为什么颤振在这里抱怨。一切都按预期工作,但我想这不是最佳实践?我该如何解决这个问题?我在这里错过了什么?

【问题讨论】:

【参考方案1】:

这是因为您应该在 State 类中操作 isSelected,而不是 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,
            ),
          ),
        ),
      ),
    );
  

【讨论】:

以上是关于在有状态的小部件中,颤振字段不能是最终的的主要内容,如果未能解决你的问题,请参考以下文章

在有状态小部件外部调用方法以使用颤振 Bloc 更新 UI

widget.something 在有状态的小部件中

为啥我无法访问小部件中的变量?

颤振有状态的小部件在热重载和 pushNamed 之后丢失数据

Flutter/Dart:我的小部件树中可以有多个带有状态的小部件吗?

在 Flutter 中使用 BLoC - 在有状态小部件与无状态小部件中的使用