I have a screen as statefull widget. When I instance it I have the same "this" in initState and build methods, as expected.
But if, from that screen, I open a new screen and than I come back to the first screen, first the statefull widget screen doesn't appear to be reinstanced, the method initState is not called again but the method build is called (as expected, the screen has to be drawed again) and it has a new "this" than the first time the screen has been displayed.
I could also accept the screen class has a new this but how is it possibile without a new instance of the screen widget?
It seems the class change its "this" without a new instance of the class.
Is it possibile? Why? Am I wrong?
By documents of flutter's stateful initstate
Called when this object is inserted into the tree.
The framework will call this method exactly once for each State object it creates.
Which means when you added the stateful widget for the first time this method is called and this (instance) is created..
Now the build method is called on various situations
The framework calls this method in a number of different situations. For example:
After calling initState.
After calling didUpdateWidget.
After receiving a call to setState.
After a dependency of this State object changes (e.g., an InheritedWidget referenced by the previous build changes).
After calling deactivate and then reinserting the State object into the tree at another location.
So each timethe build is called a new instance is created if you have added the code to create an instance in build method.
When you move to the next page the first screen is still in widget tree. Then you pop screen 2 so you see screen1 ahain but this time its not added to the widget tree so only the build is called.. if you do navigator.push from screen 2 and navigate to screen 1 you will see initstate being called again because a new instance of screen1 is added to the widget tree..
Related
Both the initState() method and didChangeDependencies() are executed before the build() method of a state object, so why is the context not available inside initState() but available inside didChangeDependencies()?
According to the official docs, didChangeDependencies() is called whenever the dependency of the State object changes. What does dependency mean here, and when does it change? (I am a beginner, so please use layman's term to explain this concept to me. I looked up other similar questions, but was not able to understand this.)
Unrelated to this topic, I understand that flutter creates elements and renderObjects for each widget it encounters in the widget tree and if that widget is a statefulWidget, then a state object is also created and a reference to that state object is held inside the element. My question is when are the element, renderObject and state object associated with a widget completely removed from their corresponding trees? Does this happen when the widget is permanently removed from the widget tree, or are they kept even after the widget is removed from the widget tree and some other widget is displayed in its place? For example, let's say that I have a floating action button on my homepage and on clicking that I'm pushing a namedPage onto the stack using the pushNamed method of the Navigator class and displaying a new page. Let's say that the new page is a StatefulWidget which has a state object associated with it, so when I go back to my home page again using the back button, that StatefulWidget is removed from the widget tree, right? Are the State object, element and renderObject associated with that widget destroyed immediately, or does flutter keep them around? If flutter does keep them around for some time, then how does it decide when to destroy those objects?
Firstly, you have to understand what is BuildContext that usually name as context.
buildContext is: the place in the widget tree in which this widget is placed.
All widgets have a bool this.mounted property. It is turned true
when the buildContext is assigned. It is an error to call setState
when a widget is unmounted.
why unsafe to use context in initState is because the widget is unmounted. means that the widget doesn't have place in the widget tree.
didChangeDependencies(): This method is called immediately after initState on the first time the widget is built.
its safe now because property mounted is true.
for the 3rd, you may know about deactivate() method. here
this is another answer for full explanation of flutter widget lifecylce :Life cycle in flutter
So I have a call a timer function on pressing the login button in the main file. The timer function is defined in the login verification file. So how can I call the timer function in main file so that when the login button is pressed and when it goes to the login verification the timer starts?
If you want to use some parent's function in child widget then it is easy - just pass the reference to the function you want through the constructor.
If you want to use some child's function in parent widget then the situation is a little bit different - you have to pass a GlobalKey to identify the state of child widget when creating an instance of this widget. You can refer to this https://stacksecrets.com/flutter/how-to-call-method-of-a-child-widget-from-parent-in-flutter.
If you want to use a function from a widget that is not either a child or parent widget, then you might think of using some state managment solution (such as Provider or GetX or Bloc) to provide it to all the widget that needs some information from it.
In my flutter app, i use a list view inside a HookConsumerWidget, this list has a filter and once it filters the list tiles have big gaps, and i see this error:
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
i couldn't solve it because its a HookConsumerWidget and its not flexible
try to show some code snippets of the problem or the log messages,
my concern is when you're using HookConsumerWidget you don't need to use setState as you could manage the UI changes directly with listeners or watcher with 'StateProvider' for example.
I'm fairly new to Riverpod but it seems that using a ConsumerWidget as the body of a screen is a bad practice because the screen is rebuilt when not needed.
For example:
the main widget (the screen itself) is a ConsumerWidget
somewhere in the hierarchy I have a list of clickable buttons, for which I'm watching a ChangeNotifierProvider to update a selected index (only one button can be clicked at a time).
It seems that whenever I click one button to update the index (and change the color of the button), the main widget's Build method is called, along with the items in my list.
However, when using just a Consumer widget inside the itemBuilder method of my ListView, clicking one button no longer triggers the build method of the main widget.
So, is it considered a good practice to just use Consumer widgets where needed?
I noticed that the build method gets called often in a flutter app.
I know that if the states of the page change in a statefulWidget, the build method gets triggered. But I also noticed that the build method is called even if nothing is changed in the app.
Considering the case where you leave the app to itself, is it normal for the build method to get called frequently? If so, why and how often?
Why
The build method is called any time you call setState, your widget's dependencies update, or any of the parent widgets are rebuilt (when setState is called inside of those).
Your widget will depend on any InheritedWidget you use, e.g. Theme.of(context), MediaQuery.of(context) etc.
This means that if the theme changes for example or the screen orientation swaps, your widget will also be rebuilt.
When you use widgets like MaterialApp, Scaffold etc. that are provided by the framework, your widget will be rebuilt a lot because these parent widgets depend on many InheritedWidget's and then are rebuilt, which causes your widget to be rebuilt as well.
How often
There is no number for how many rebuilds are "normal" as this completely depends on your tree size and most importantly widgets are in that tree. If you were to run runApp(Container()), there would be no rebuilds.
Just keep in mind that all of these rebuilds probably have a good reason to occur and Flutter is built for this, so you do not need to worry about this.
The only point you should start worrying is when you have constant rebuilds that are probably caused by some builder (which calls setState internally) you are using incorrectly.
Exactly when
The documentation lists all specific cases when rebuilds can occur:
After calling initState.
After calling didUpdateWidget.
After receiving a call to setState.
After a dependency of this State object changes (e.g., an InheritedWidget referenced by the previous build changes).
After calling deactivate and then reinserting the State object into the tree at another location.
Rebuilds from parent widgets
If you want to understand how InheritedWidget works, see this answer. It also touches when a rebuild in a parent widget causes the subtree to rebuild.
After calling initState.
After calling didUpdateWidget.
After receiving a call to setState.
After a dependency of this State object changes (e.g., an InheritedWidget referenced by the previous build changes).
After calling deactivate and then reinserting the State object into the tree at another location.
Read this for more info https://api.flutter.dev/flutter/widgets/State/build.html