I was new to the flutter so I build a full application without using state management, all my screens in the application built with the stateful widget
what is the danger of that if many users used it?
You risk not being able to scale your code well. From passing data down the widget tree to passing data to screens etc., this will require a lot of lines which will lead to un-maintainable code. For small projects though, you don't really have to use state management libraries such as BLOC and Scoped Model.
As the project scale, I believe you will have performance issues due to using setState() and without inherited widget your UI will re-render again every small change or action in your screen.
Also, Your code will get complicated as project scale because you are not separating your logic in a separate file (using bloc, provider or whatever), It will be a mess as UI and business changes.
Most users won't know the internal architecture of your app unless they are good programmers themselves. But the goal of building applications is to attract users, and expand customer base. And this will require you or your company to add additional features in the future to accommodate their needs, and when you try to make even a subtle change to the source code, it will take more time and you will be prone to add new bugs to your application as your models and views are all mixed together.
Another reason is that you can't (as far as I know) test an app which doesn't have any type of state management.
Related
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:
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
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
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
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:
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.
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.
Same as the above, also a lot of boilerplate code.
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.
I'm slightly new to Flutter and just want to ask some questions/clarifications regarding the development using it. I am currently building a flutter app and wanted to change the layout based on different devices and orientations. I created 2 different dart files containing different app layouts of my Login page (LoginMobile.dart and LoginTablet.dart respectively). I created also a separate dart file (LoginComponents.dart) to store "all" the object UI/components of my login form (txtEmail, txtPassword, btnLogin, etc.). I heard doing like Widget txtEmail() {return TextformField(...);} is not advisable as it can affect the app performance, so I tried making them as classes. Am I doing it right? Is it okay to store multiple stateful widgets in one dart file(?) since the txtPassword have a setState() for show/reveal password and the btnLogin for the authentication process. Is there any negative effects that I may face in the long run if I continue doing it this way? Any tips and advise were highly appreciated. Thanks!
Storing your widgets in a single file is okay but would cause confusion when making a large app. when the amount of widgets is getting increased in that file it would be harder to do a small change because its harder to find the widget.
i would recommend using multiple files, so you can find them and organize them easily.
Yes, you can. But point comes to maintainability. I prefer to keep one public widget which having the same name as the filename and remaining private widgets.
So now ques is How many widgets in a single file?
Its actually depend there is no such rule to restrict the limit of file. Different authors having different preference. I prefer try to keep 5-6 classes(widgets) and
each one having 5-6 functions.
Try to make a file single responsible i.e(5-6 classes together responsible for single functionality). Don't make god class which having unrelated concerns together later it will pains(haha)
If it's a common widget keep them separate to respect DRY principle(Don't repeat yourself)
If the widget is further divided into 3-4 widgets or it children widget change depend upon rest response keep seprate for good practise
Bonus Tip: try using code folding shortcuts to push a little more
Am I wrong or if we just want to pass a value down the Widget tree, Provider is just an InheritedWidget with a dispose method?
Yes. Provider is indeed mostly features based on Inheritedwidgets.
If you want to make your own, then that's fine. But you'll quickly realize that, without provider, you'll have hundreds of useless repetitive lines.
Provider basically takes the logic of InheritedWidgets, but reduce the boilerplate to the strict minimum.
Provider is not a must, but should.
First of all, it's promoted by Flutter Team and flexible enough to handle almost any state-management solution.
It might not be fair to say that InheritedWidget with dispose because Provider has too many different use cases and inherits some optimizations probably you won't find anywhere else.
If you use InheritedWidget in large application, build methods always rebuilds whole build method. But with Provider you have Consumer widget which is can be very specific to control specific blocks of build method, so you have more efficiency. Also listeners have less complexity than InheritedWidgets'(O(N) vs O(N²)).
The problem is since Flutter was intended to be a UI framework at first, the default state management solutions are also UI oriented.
Lastly, since you'll need different state-management patterns for different projects, one package-for-all scenario is invaluable imo.
The Flutter docs have a good section about this where they're talking about state management in your app (a big part of which is passing values down the tree).
Flutter has mechanisms for widgets to provide data and services to their descendants (in other words, not just their children, but any widgets below them). As you would expect from Flutter, where Everything is a Widget™, these mechanisms are just special kinds of widgets—InheritedWidget, InheritedNotifier, InheritedModel, and more. We won’t be covering those here, because they are a bit low-level for what we’re trying to do.
Instead, we are going to use a package that works with the low-level widgets but is simple to use. It’s called provider.
So as of late 2021, it seems the recommendation is to use the provider package unless you need lower level access- in which case you could use the Inherited* widgets. For example, if you wrote your own version of provider then you'd need that lower level access.
The doc I quoted above is at https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple#accessing-the-state
I need manage the states globally, I find a lot of way, in terms of managing the state by using Provider bloc pattern redux and etc.
But actually I dont know, which one is faster and performant?
Example: I am working on chat application, which I have to manage socket connection messages online offline status all as globally. the states need to be accessible from all screen, like ChatList screen, ChatBox screen and more...
I didn't test them all performance wise. And i do not think it will make much of a difference.
Provider works with inheritedwidget as scoped model i think.
I love the streams for the versatility of the data flow.... i think the key part for performance is to keep the rebuilding/painting of the widgets that require it at the lowest level of the tree.
get_it package should help you to keep those streams accessible everywhere, is a great simple package to keep neat model access, regarding the state management solution.
For instance, i believe that generating statelessstateful widgets instead of functions that returns widgets to make the layout, provides more performance, for the separation of buildcontexts.
In any case, the framework is super optimized and performant... if u run into any issue, u can easily track it down with the devtools and the community is very supportive.
Btw, take my basic reply with a grain of salt, as I've been only playing with flutter/dart for a week.
What is the best practice way to manage multi panel (i mean page) application for GWT (in terms of performance, memory usage etc.)
Should i create all widgets and change their visibility or create and remove widget on request.
You might be interested in Large scale Application Development and MVP in terms of best practices to manage a multipage application.
Speaking of re-using Widgets (since they are costly to build) a factory approach to produce them on the fly and keep the instances of costly ones for re-use has worked well for me so far. One thing to keep in mind is to clear the states(values of textboxes etc.) before re-using them. Unless my page is a multi-panel page with hundreds of widgets, I prefer creating them on the fly, instead of re-using, since it has no noticable impact on user performance. I beleive memory should not be an issue unless your app consists of thousands of pages and you keep a reference of each and every single one of them.
Last but not least benefit of using a ClientFactory is you can switch your factory implementation with another-one (ClientFactoryMobile..) with deffered binding depending on the platform your app is being loaded thus making switching user interfaces a breeze.