0

I'm utterly confused regarding the question of state management in Flutter.

So far I have read that the states of widgets have to be nested as deep in the tree as possible (or rather as close to the affected widget as possible) for better performance.

But what if such a nested state widget (InheritedWidget for example) has another state widget somewhere above it? Does the state widget at the lower level not loose it's state when the state widget higher in the tree requests rebuild for all of its descendants?

With this line of thought have I came to the conclusion, that state widgets just have to be at the root in the end, but I guess I'm wrong somehow.

Ketto Egy
  • 13
  • 3
  • Yes, you are right, so you need to use state management plugins, use their ideas to locally update your UI, instead of simply using SetState() – bakboem Jan 07 '23 at 11:46
  • To all my foreigner friends, this might just be the proper thread answering my question:https://stackoverflow.com/questions/49491860/flutter-how-to-correctly-use-an-inherited-widget?noredirect=1&lq=1 – Ketto Egy Jan 07 '23 at 12:09

3 Answers3

1

The first part of your question is correct - If a widget's state changes, this might require all its children to redraw.

But this is precisely why it is important to nest state as deep down in the widget tree as possible!

Assume the contrary, that all state information is stored at the root of the widget tree, at the very top. Now if any information changes, no matter how small, it will lead to a complete traversal of the widget tree, rebuilding everything in the worst case.

And aside from the tree traversal, your application will also become very memory intensive. If all state is stored at the root, flutter can never tell when it is okay to release some information from memory. If the user leaves some views and the views are dismissed from memory, the information for them will still be stored at the top. And the only way to check wether that information is still needed would be to once again check the whole tree - very expensive!

All of this can be mitigated by putting your state as close as possible to the widget that will consume it. Because then

  • If the state changes, only a small subtree of the whole widget tree has to be traversed - This is fast.
  • If a widget is dismissed, flutter can also release all of the state information that has been stored for it. This frees memory.
jraufeisen
  • 3,005
  • 7
  • 27
  • 43
  • but what if I need the data that was "associated" with a widget that got -as you put it- dismissed later on? I guess I had to recover it from an InheritedWidget sitting higher in the tree, but this just gets us back to the beginning: a central root state has to be kept in memory. I still think I'm missing something, but I guess you too. I'll update my question with a proper example when I figure one out. – Ketto Egy Jan 07 '23 at 12:51
  • As an example: Imagine that you want to show a new view with a switch (on/off) that corresponds to a user setting. You are right, you will need to store that information somewhere and load it into memory when you present the view. But when you dismiss the view, you don't have to keep that setting in memory. You can store it elsewhere (SharedPreferences, NSUserDefaults, a database, a webserver, whatever) and retrieve it from there when you will show the view the next time. This is your "root state" if you wish, but it lives outside your app – jraufeisen Jan 07 '23 at 13:50
  • thanks for your comment, for the time being I think I'll just resort to using provider, then sometime I'll dig into this topic again. – Ketto Egy Jan 07 '23 at 14:05
  • I've been thinking about it recently again, and: you are talking about persistent storage of state, but the loading of the state still have to be buffered into memory anyways. Well, yes, a top level buffer can be skipped I guess in favor of an InheritedWidget nested lower in the tree that has some persistent storage reading constructor that loads the data each time, or... How do you set a callback to save the state when the widget is destroyed before rebuild? Excuse me pls if I'm talking bullshit here, which might very well be the case, I just can't find a good thread on this topic. – Ketto Egy Jan 10 '23 at 19:20
  • And arguing in favor of root level state, isn't it just what the provider package does? After using it right now not really knowing how it actually works, I realized (maybe falsely), that while having a root level state, one can still nest smaller pieces of it in the tree to improve performance. But if a lower level Consumer gets rebuilt, it can load its data from the root. Again, I'm guessing here, please correct me if I'm wrong, lest my line of thought makes any sense. – Ketto Egy Jan 10 '23 at 19:25
  • You are touching upon many important topics here and I fear it will be too much for a SO comment thread. But it seems to me you are on the right path. If you want to dive deeper, it can help to get familiar with architectural patterns like MVVM. This will answer the question on how you can save state (to a persistent storage) when a widget changes – jraufeisen Jan 10 '23 at 19:39
  • 1
    Thanks for the feedback again, I'll check MVVM out (I've already stumbled upon it once but have not dived into it). If I figure something out and post a topic somewhere I'll leave a link here, or if I just find something meaningful leaving a link of it will also be the case, guessing again on both branches of possibilities of the future,,, I guess... – Ketto Egy Jan 10 '23 at 20:03
1

yes ! every state widget has its own state and they are all independent. if the state of widget X is updated, only widget X will be updated

let suppose that you have an application that sows a family tree. in widget A you get the gradfather from an API, when you click on it you will be redirected to widget B where you can find his childrens, when you click on one of his childrens you go to widget C which shows the childrens of the selected father in widget B, now let's supposse that you want to add one children to this father. you call the add-children endpoint. the problem here is that widget A will not be updated.

one solution to this, and to understand the state tree logic, is to pass a functionthat updates widget A from widget A to widget B and pass it from widget B to widget C and call it when an update happens either on widget B or C or even on A so widget A gets updated and you got the updated family tree in widget A

Ahmed Sbai
  • 10,695
  • 9
  • 19
  • 38
0

So basically flutter have it's own state management that is called setState(() {}) itu will update the state of the screen where setState is called if i have a button class widget in it's own file if i press the button i want to change the button name to something else so the setState will update the state or variables in the button class/widget.

Now how if the button wants to update a state/variables in the different class but in same screen? Since setState only update it's own class, so you to give the button onTap property with function constructer like this final Function onButtonTap; then put it on onTap like

onTap:() {
widget.onButtonTap();
}

    

Then in the screen where you want to update the state just call onButtonTap then use setState there

CCP
  • 886
  • 1
  • 10
  • 30