Class marked as @immutable, instance field not final using StatefulWidget

7.7k views Asked by At

I have a Stateless widget called ToggleButtonsList and one of my instance fields, isSelectedType, is not set to final. This is the warning I am receiving because of this:

"This class (or a class that this class inherits from) is marked as '@immutable', but one or more of its instance fields aren't final: ToggleButtonsList.isSelectedType"

Here is a portion of my code:

class ToggleButtonsList extends StatefulWidget {
  ToggleButtonsList({this.type, this.stringList});

  final String type;
  final List<String> stringList;
  List<bool> isSelectedType = [];

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

class _ToggleButtonsListState extends State<ToggleButtonsList> {
  @override
  Widget build(BuildContext context) {
   
   
  }
}

My question: I thought instance fields needed to be set to final only for Stateless widgets, NOT Stateful Widgets. Is this true? Is this a warning I should worry about since I'm not using a StatelessWidget or can I ignore it? My app seems to be working perfectly fine when I ignore the warning.

Reading the "or a class that this class inherits from" part of the warning made me try searching my project for any StatelessWidgets this class may inherit from and the only StatelessWidget I have in my project is from my main.dart :

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
          primaryColor: Colors.blueGrey,
          scaffoldBackgroundColor: Colors.blueGrey),
      home: PriceScreen(),
    );
  }
}

Changing my MyApp class to a StatefulWidget didn't get rid of the warning.

2

There are 2 answers

1
Mehmet Esen On BEST ANSWER

I think your mixing State and StatefulWidget class. The Widget class itself is immutable and both StatelessWidget and StatefulWidget extends from Widgetclass.

In your specific case, isSelectedType variable can be final, because final collections can grow or shrink. Only constant collections won't allow you to grow or shrink.

What you need to do:

class ToggleButtonsList extends StatefulWidget {
  ToggleButtonsList({this.type, this.stringList});

  final String type;
  final List<String> stringList;

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

class _ToggleButtonsListState extends State<ToggleButtonsList> {
  List<bool> isSelectedType = [];

  @override
  Widget build(BuildContext context) {
   
   
  }
}
0
Lesiak On

Both stateful and stateless widgets need to be immutable. This is enforced by @immutable on Widget class.

See Flutter: Mutable fields in stateless widgets:

Stateless widgets should only have final fields, with no exceptions. Reason: When the parent widget is rebuilt for some reason (screen rotation, animations, scrolling...), the build method of the parent is called, which causes all widgets to be reconstructed.

Classes the extend StatefulWidget must follow the same rule, because those are also reconstructed. Only the State, which can contain mutable fields, is kept during the lifetime of widget in the layout tree.