3

I am writing a relatively simple app in which I need to do some state management. After looking trough all the documentations and many rewrites I need help with understanding how to actually structure and use the tools provided for state management, like the classic providers and riverpods providers. My questions concern the arrangement of Models which hold state, nesting those objects and redrawing only parts of the widget tree.

My project is a mobile app which lets you keep a shared log of your fuel stops and the money you paid. If you share a vehicle with one or more persons, you all enter a pool in which the fuel entries are displayed. There are models for users, log entries and pools. When a user is logged in, a number of available pools need to be fetched and stored and after selection the members and logs of the selected pool need to be fetched. If updates are made to e.g. the name of the user or a specific log entry, the current view might need to get updated.

Now, the current code is a mess where much of the state gets stored in a pool model, which is provided by a ChangeNotifierProvider at the root of the widget tree. Since I was under the impression that one should try to update as little of the UI as possible I tried to split my state up into different models, which are nested into each other, for example the LogEnries are part of the pool model, but are themselves ChangeNotifier. The idea was to be able to selectively refresh and listen to parts of the state. This has lead to horrible code where I sometimes need to call notifyListeners() from outside my pool model / state object. I want to remedy the situation with a rewrite of my state management.

Now to my question: How would one structure state generally (or my state specifically) for it to be efficient and pleasing to the magical gods that created the libraries? This stackoverflow question from two/one year ago asks a similar question and the provided answers recommend to do one of these things:

  1. Leave the state nested and inject the Models into each other with ChangeNotifierProvider, but apparently that's not great if the provided objects are models
  2. Put everything in one state object whose provider sits at the top of the tree, and maybe use a selector to only refresh the part of the UI which is affected
  3. Nest models but only provide the root an as immutable object and update state by calling functions and copying stuff

I think another approach would be to

  1. use the recently released riverpod package and create a lot of providers for every need.

Now I have no idea which of these approaches is better or valid or if they all work perfectly fine. My questions regarding the corresponding approach would be:

  1. In what order would I nest them? I intuitively nested the Pools in the root state object, the log entries in the pool model but dependency wise I'd probably have to go User->AppState->selectedPool->Logs, resulting in a possible statement of logEntry.selectedPool.appState.user. Feels weird.

  2. This might work but I'd always get the whole state in one model (which is arguably not that big in my use case). One could use the Selector to only refresh parts of the UI, but I think there was a problem with using mutable objects for that because Selector needs to be able to tell if something has changed. Also, as far as I understood I could only use the stuff I've specifically selected and not listen to a different property than the one I'd use afterwards for UI refresh.

  3. Same as the above, also a lot of boilerplate code.

  4. This one seems the most exciting, since riverpod and it's providers look really cool. But would I nest my state or just provide everything globally and maybe inject a few things with ref.watch() in the creating method? Would I create a new provider for every change which I want to listen to separately or is it cheaper to figure that out once I get the object? And since the riverpod equivalent of ChangeNotifier, StateNotifier features only one Value (I think?), would I create a new provider for every important piece of information I need?

As you might have noticed, I tried to look up a lot of stuff but haven't quite figured out how to translate all the techniques to an actual project beyond code demonstration size. I would be immensely thankful if someone could explain to me the correct approach to structuring state management in general, which approach might be the best one for my specific situation and most importantly what might be the reason to decide against other ones. Please don't hesitate to point out any mistakes I made, although stackoverflow has a reputation suggesting this might not be an issue. If anybody wants to have a look at my code, there's a branch where I started to work towards a better modularization starting with an AppState Model and reworking some functions.

Dharman
  • 30,962
  • 25
  • 85
  • 135

0 Answers0