What is the Use of initState in Flutter?

Learn via video courses
Topics Covered

What is initState in Flutter?

The word initState is made up of two words: the first word being init, which means initialize, and the other word being state. It is a method of the State class that is used to initialize the state of a Stateful Widget. When the stateful widget is inserted into the widget tree for the first time, initstate is called. It is also used to set up necessary data before the widget is rendered on the screen. Overall, it plays a very important role in the lifecycle of a StatefulWidget for it provides a convenient entry point for preparing the widget's state.

What is the use of initState in Flutter?

The main use of the initState is to perform initialization tasks which are important for the widget's functionality. It allows us to execute the code which must be run before the build() method is called. State variables hold data that can change over time. initstate helps us to set up their initial values so that the widget starts with the desired initial state. It is also used to execute setup tasks like setting up listeners, initializing controllers or animations, connecting to external services, etc. By performing these setup tasks in initState, we ensure that all the necessary components are ready before the widget is displayed. If we have to fetch some data from APIs, databases, or other sources, using initstate ensures that we have the data before the widget is rendered. Streams are used to handle asynchronous data. Using initstate helps us update the widgets and trigger rebuilds whenever new data is received

Uses of initstate in Flutter

a) To initialize data that depends on the specific BuildContext:

initState allows us to initialize data that depends on a specific BuildContext, which in turn provides information about the widget's location in the widget tree. The most common use case of this phenomenon is to fetch data from APIs, databases, or other sources. For example, If you have a StatefulWidget that needs to fetch user data from an API then using initState ensures that the data will be available when the build() method is called. In the example shown below: The fetchUserData() function takes the BuildContext as a parameter and is called to retrieve the data. The fetched data is then stored in the userData variable, which is used to display the user data in the build() method.

b) To initialize data that needs to execute before build():

There are times when we need to execute some data before the build() method is actually called. We need to set up variables, initialize state, etc. as they are essential for the widget's functionality. In the example given below: We have called the initializeData() method inside the initState() method. It ensures that the counter value is set before displaying it on the screen.

c) Subscribe to Streams:

Streams are used in Flutter to handle asynchronous data. By subscribing to a Stream in initstate, we can listen to the data events emitted by the stream and update the widget accordingly. In the example given below, we use the _subscribeToStream() method which sets up a stream using the Stream.periodic() constructor. The count is incremented every second and then the setstate is called in order to rebuild the widget. To prevent the memory leaks or unnecessary usage of resources, we call the subscription?.cancel() inside the dispose() method;

Limitations and Best Practices

Having discussed the use cases of initstate flutter, it is equally important to know about its limitations and the best practices we need to keep in mind while using it. We are going to discuss some of its limitations and best practices.

Limitations:

1. Context-Dependency: initstate is called before the widget is inserted into the widget tree and therefore, the widget's BuildContext is not available at that time. We cannot use context-dependent methods and properties such as MediaQuery or BuildContext etc. If we need to access those properties then it can be done by deferring the task to a later point in the lifecycle such as didChangeDependencies() or build().

2. Inability to perform heavy computations or I/O Operations: initstate is called synchronously during the widget's installation and therefore we should avoid heavy computations or I/O operations in this method. Doing such tasks can make your app unresponsive by blocking the UI thread. You can perform such operations safely by deferring them to a separate isolate or using asynchronous methods like Future.delayed().

Best Practices:

1. Focus on initialization and minimal setup: It is recommended to focus on the essential tasks only using the initstate and leave the rest of the tasks to be handled by the subsequent widget lifecycle methods.

2. Make Sure to Dispose the Resources: In order to avoid memory leaks or unnecessary resource usage, we should make sure to properly dispose of these resources. We should also make sure to cancel all the subscriptions and release any resources that are no longer needed.

3. Handle Potential errors carefully: If the initialization depends on certain conditions then we need to carefully handle them and communicate to the user. For instance, if we are fetching data from an API then we must check for internet connectivity first.

Example App

example flutter app

Github Repository Link: https://github.com/shashwatssp/scaler_initstate/blob/master/lib/main.dart

main.dart file:

Github Link: https://github.com/shashwatssp/scaler_initstate/blob/master/lib/main.dart

demo.dart file:

Github Link: https://github.com/shashwatssp/scaler_initstate/blob/master/lib/demo.dart

This page redirects the user to other pages.

init_data_dep_on_buildcontext.dart file:

Github Link: https://github.com/shashwatssp/scaler_initstate/blob/master/lib/init_data_dep_on_buildcontext.dart

This code demonstrates dependency on the BuildContext object. It initializes _data based on the current route name and displays it in a Text widget.

init_data_exec_before_build.dart file:

Github Link: https://github.com/shashwatssp/scaler_initstate/blob/master/lib/init_data_exec_before_build.dart

This code demonstrates executing code before the build() method is called. It initializes _data with a string value before the widget is built and displays it in a Text widget.

sub_to_stream.dart file:

Github Link: https://github.com/shashwatssp/scaler_initstate/blob/master/lib/sub_to_stream.dart

This code demonstrates subscribing to a stream and updating the UI based on the stream's values. It creates a stream that emits a value every second and updates _data accordingly, displaying it in a Text widget. The stream subscription is canceled in the dispose() method to clean up resources.

Conclusion

  1. initstate is called when the stateful widget is inserted into the widget tree for the first time.
  2. It enables to perform the necessary setup tasks before rendering.
  3. It enables subscribing to streams and updating the widget's state.
  4. We need to avoid heavy computations or I/O operations inside the initstate flutter.
  5. We should dispose the resources after they have been used and handle the conditional initialization as well.