HookConsumerWidget in flutter causing dispose errors - flutter

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.

Related

Why is context safe to be used inside didChangeDependencies() method but not inside the initState() method?

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

Reordering an 'active' widget in flutter with Reorderables package

I'm using 'package:reorderables/reorderables.dart'
I use the ReorderableColumn which contains a column of widgets. The 'normal' drag/drop works fine when the contents of the widgets are not changing.
The issue is that if the widgets being dragged is 'active', as in there is some activity going on that is causing rebuilds (a file is being uploaded, and there is a progress indicator, status updates etc), the system crashes with messages like:
Error: setState() called after dispose(): _FilePickerWidgetState#174b4(lifecycle state: defunct, not mounted)
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.
From what I understand this package removes and inserts the widget from the widget tree for a more realistic visual simulation.
Could you suggest a solution or alternative?
I was able to replace this with the Flutter build-in ReorderableListView - there are less controls available, but I no longer get any errors.

Flutter setState rebuilding all children

I've got a parent widget that has a Stack with two children.
When using setState in the parent, without actually changing something (setState with empty body) why are the build methods of the children being called?
Is it not the case that flutter rebuilds only the widgets with dirty params?
Flutter will run the build function for all children (exception being const Widgets). It will not rerender them though. If Flutter finds that nothing changed in the widget, it will just reuse the previous render.
The program has no way of knowing if state has changed, unless it checks by running build.

How often is the build method called?

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

How many setState() calls is overkill for Flutter?

I am new to Flutter and reactive programming is also new thing for me.
Let's say I want to build a timer with Flutter.
I add a Scaffold with all the necessary stuff in it and I add a IconButton which starts the Stopwatch and Text which displays elapsed time. I also add Timer.periodic to periodically (every 0.5 second) update the text.
Text Widget controls it's own state by checking if Stopwatch is running and updating it's values.
So now let's say I want to have more complicated logic that changes the text based on some actions with other buttons which are the siblings of Text. However it is not possible to call setState of Text widget directly from sibling widgets. As I understand the point of reactive paradigm is that the state can be passed down the Tree. However if I make my Scaffold as StatefulWidget and update the state of the parent every 0.5 second it will redraw my entire Scaffold with all it's children. So eventually when the Scaffold gets big enough it will have to update everything instead of single Text widget.
Am I correct? And is there any solution to this. I read something about Streams and Sinks however it looks very complicated and I think that there should be another solution.
You don't need to rebuild the whole tree, if the state only changed in a sub widget, ideally you want to call set state in that widget so only that part of the tree (the one whose state changed) is rebuilt.
Streams aren't really that complicated, it's a good way for you to send messages between different components in your app, which is what you're trying to do here.
In your case you can also use a ValueNotifier to store state in the parent widget, or maybe an AnimationController, and send its listener down to the sub widget that needs be updated on change.
In any case, the state is lifted to a parent widget, which then becomes accessible to the sub widget through a listener, or a stream. When the listener triggers a signal, you rebuild the sub widget only.
Extract out widget and call setState() form that widget and it's don't render all the widget again