What is the difference between the following var initialization positions in a StatefulWidget?

Issue

I was wondering about where to declare and initialize variables in the case of a StatefulWidget. There seem to be a couple of ways to do it, but are there differences, any guidelines, or best practice approaches for it?

I created the below sample, but can not find any differences except that when performing a hot reload, variable i loses its value and is back to zero again.

I read this, but it contains so many contradicting comments.

class Sample extends StatefulWidget {
  int i=0;
  late Object object1 = Get.put(Object());
 
  @override
  _SampleState createState() => _SampleState();
}

class _SampleState extends State<Sample> {
  int j = 0;
  late Object object2;

  @override
  void initState() {
    i=5;
    j=5;
    object1.param="value123";
    object2=Get.put(Object());
    object2.param="value123";
  }

  @override
  Widget build(BuildContext context) {

  }
}

Solution

First, if you run your app on the emulator you can indeed find no differences. But, that observation is huge misleading!

Variables declared whether initialized or not inside the Widget class are not persisted in the case of widget recreation. StatefulWidgets (and all Widget subclasses) are thrown away and rebuilt whenever configuration changes. Luckily, you can force performing Widget recreation by performing a hot reload on the widget while you are testing your app. to ensure proper behavior.

If you want to declare variables that should persist (State data), make sure to put them inside the State class as int j in the above code example.
Use initState() for variables that you cannot initialize within the declaration statement.

Why then object1 retain its data?

Simply, because GetX will not recreate a new instance of Object if one already exists. It will return back the old instance every time the Widget is rebuilt. That’s why no difference is perceived in the case of object1 and object2 places of declaration.

At the time of writing this answer, you have to manually call Get.delete<>() in order to dispose a controller if you are not using bindings.

Answered By – Mena

Answer Checked By – Marilyn (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *