I would like to briefly ask something that is perhaps a little strange.
In general, there are several design patterns for developing an app (MVVM, MVC, MVP).
In Flutter there are packages that make state management easier.
Bloc
Cubit
Redux
MobX
Riverpod
flutter_command
Momentum
Flyweight
Flutter Hooks
The question is, can the packages be clearly classified in one of the architecture or is it recommended to implement a certain architecture with the package?
For example, I understood that BLoC follows an MVVM concept, while Momentum uses the MVC pattern. Is that right?
Can someone add to the list for the other packages?
Simply,
No, you can not classify state management mechanisms as a design pattern or architectural pattern. State Management & Architecture are two different things.
Why
Flutter is classified as a declarative framework, which means UI is built again & again based on the current app state ( simply current data/ information). So, Flutter State Management is used to share the app state within the widget tree. That's it.
On the other hand, app architecture is about overall communication among different layers on the app, like how UI talks to controllers, controllers to database, web service, parses, models &, etc
Related
I've been coding with dart and flutter for over a month now, one thing that I was recommended to do by my friend is to learn Bloc as it would be helpful for big projects for businesses. From watching Videos on Youtube, reading documentations on it and also looking at Github repo's I've still not understood why we need to use Bloc and its features (FYI: I've only started using Bloc the last 2 days') Would appreciate if someone would explain what's the purpose of using Bloc as opposed to just normally coding.
Benefits of using Bloc pattern
It follows SOLID principle.
Your business logic is decoupled from the UI.
You can use same Bloc object in various screens. For example if you are developing e-commerce app, you might want to show cart icon with items added on many screens and items could be added to cart from any screen, you don't have to pass around Cart object or Function to addToCart.
You instantly get notified when Bloc state is changed and you can build your widget based on new state. This also handles unnecessary builds.
You can change any implementation of business logic (like form validation) in the bloc and your UI will not need any change.
Adding Analytics to the app is also convenient.
Less logic in Widget classes means easier readability.
You can transform events passed to Bloc. (in case if you are showing search bar and on every letter type, you are making a network call to show search suggestion, you can add debounce to certain time).
You don't have to check for Authentication in every screen.
You can respond independently to various state changes of Bloc for showing Snackbar/Toast in any screen.
Less number of items passed while creating widget class (as many properties can be accessed from Bloc object)
Follows MVVM pattern which says model, viewmodel and view should be independent of each other so that future modifications/ scaling/ debugging is easier.
There could be many more benefits which others can tell. You will only realize them once you would have started using the Bloc after working with a project which does not have state management.
Sidenote: flutter_bloc library is an option to implement Bloc pattern. Bloc pattern was showcased by Google and you can write your own implementation as well. But the flutter_bloc library is very robust.
BLoC or any state management protocol will only help you to separate data and presentation layer in your project. It will prove useful when a company has to grow its tech team or if they are planning to separate front-end and back-end development.
There is setState and moreover Provider, using which you can manage your states easily and neatly, then why Riverpod?,
I see different examples in enter link description here where riverpod is being used, I just find each example making simple things more complicated, when you use Riverpod, same things can be done more easily with Provider or just using setState and following some good techniques while managing states in codes.
there is a package named hooks_riverpod, I don't find the justification of this package just to support riverpod you hacked all the statndard widgets although there is another version flutter_riverpod but using hooks is not an intended approach maybe helpful for people coming from reactjs background but flutter engineers have not designed flutter this way, using these non-standard approaches you are just trapping yourself within the mercy of these few packages.
Inherited widgets is only standard approach given by flutter of managing states across the app, Provider and some other Packages like Redux they just follow the same approach.
If you may have used the Riverpod or related packages please share your experience.
It depends on the project and how you like to handle state. If you are ok with setState management/Inherited widgets, you don't need to use others.
I like share some reference here, On riverpod doc second section you can find
Provider, without its limitations
Riverpod is inspired by Provider but solves some of it's key issues such as supporting multiple providers of the same type; awaiting asynchronous providers; adding providers from anywhere, ...
riverpod, Dart only (NO flutter)
flutter_riverpod, A basic way of using Riverpod with flutter. You mostly use it for state management.
If you are using hook widgets(flutter_hooks) that reduce the boilerplate code like dispose, you can use hooks_riverpod
Also, all these packages provided by same author Remi Rousselet
Well, there's a lot of debate on a good state management solution out there.
But in your context, I'd like to mention some points.
Why Riverpod over Provider?
Well, Riverpod was built to fix some issues of Provider which would have been impossible to fix in Provider.
Like:
Majorly, Riverpod is compile safe.
Solves stuff like multiple providers, adding providers from anywhere.
Removes Flutter dependence, there's no need of using contexts anymore like that were used in Provider.
and others... for more on that you can refer to the home page of Riverpod here
Also, Remi, the creator of Riverpod & Provider suggests using Riverpod over Provider.
Secondly, why not setState?
Well, you can't build a featured application just using setState with proper programming standards. You would have to pass up and down data in your application continuously with Prop Drilling. Imagine having 5 widgets under a parent widget and the parent widget needs the data in the 5th sub widget. This is just a normal case, it could go much worse in actual applications.
About hooks?
Well, yes, it's well easy for React devs to quickly jump on to Flutter. But that's just not the case it was developed for. Its main purpose is to use reusable functional widgets. So, a good example of this will always be, when you're using Animation Controller and you've to maintain its lifecycle every time you use it. I can't go in depth here, for that you can refer to the docs.
I'm relatively new to Flutter and Cubit pattern and I'm trying to figure out which are the best ways to work with them. Recently my colleague and I have been struggling to reach an agreement where we should inject the cubit and the repositories.
Reading the bloc/cubit documentation, it is not very clear about where we should do it.
IMO, everything that we need to instantiate, should be injected as high in the tree as possible where two different components that will use this information have in common.
For my colleague, each widget can instantiate one cubit, meaning that each widget will have its own instance of the cubit.
I would like to discuss about what are the community thoughts and best practices regarding the dependency injection and architecture regarding cubit.
There is no single answer to that question. It all depends on your project structure and architecture. In general though:
It's OK to create a few cubits/blocs in one screen/widget. Some widgets or screens contain more than one business logic stuff. Cubits are just classes that help you maintain the state, but it's no different than having many animation controllers or text editing controllers, it's just that it serves a more high-level state management. Let's say that you have a comments section in your app. You may have:
a cubit for the comments themselves, to load them, load more on scroll, report error when loading failed etc.
a cubit for each comment that manages the "Like" button under a comment
It's perfectly valid to have it that way.
It's OK to have global cubits for the whole app. There are some things that you need to have access to from the whole application. It usually is navigation (Navigator), and some theme management (Theme), why not something more business-logic related then, like authentication logic, current user context, user's app preferences, etc.? :)
IMO, everything that we need to instantiate, should be injected as high in the tree as possible where two different components that will use this information have in common.
This is a good approach. Most frequently it will be above your routes, so somewhere above your MaterialApp. If you make use of nested Navigators, then this common place could be above this nested Navigator.
On a more technical side, how will you manage the dependencies used in those cubits/blocs is up to you and your liking. I find some of the options:
Instantiating all repositories and other dependencies in main.dart method and then passing them in constructors to your blocs/cubits in Providers.
To reload those dependencies you will need a Hot Restart though, Hot Reload won't be enough.
Putting your dependencies in the widget's tree with Provider, just like blocs/cubits.
Using riverpod instead of provider.
Using a Service Locator pattern with get_it and injectable combo.
The most correct choice will be something that you (and your colleagues) are most comfortable developing with and that scales well.
I want to know what is the difference between getx and riverpod. I am so confused about which one of these two state management tools I will use in real projects.
Here is a good and very recent YouTube video on the topic:
https://www.youtube.com/watch?v=mxkhUYC5yF8
However, I suggest you to look at BLoC and especially using its cubits.
Riverpod in my opinion is not a good choice since they decided to completely reinvent the wheel, not using InheritedWidget but instead implementing their own solution. I would never want to be working against a framework, but rather with it.
The difference is that Riverpod follows unidirectional data flow and getx doesn't.
go for riverpod for large products,
go for GetX for small applications.
GetX is not just a state managing tool, it more like a framework for flutter. If you only want a state manager you will get all of these extra functions and utilities you don’t need. And if you use all of what GetX have to offer, your entire routing, materialApp, localization, api, etc is dependent on one package. Having your application dependent on both Flutter and GetX to be maintained is an unnecessary gamble imo. Especially if it’s a production app.
I am new to clean architecture in flutter,
I know that we should inject our repositories via usecases into presenters like BLoc but I don't know how to use services like an audio service, for example we should pause, resume, seek and ... from the audioServiceImpl,
does it need a usecase for each opearation like play or we should inject the service directly into BLoc ?
You've not mentioned to the layers you've adopted from the clean architecture
and the use case you need to consider such a design, so it makes your question opinion based.
A service like audio player is
more a UI related thing and it does not contain business logic,
as it mentioned in the clean architecture use cases layer contains application specific business rules. You should clarify how your playing file involves business logic. Although you still can use bloc for player state management.