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.
Related
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.
This may be a noob question but I am new to Flutter. Hearing all those keywords: "State Management, Provider, Redux, MVVM and Bloc", I get a little bit confused.
When implementing the Bloc pattern, is it that you already implemented state management? Does this (in most cases) mean that I do not need to use another tool like Redux or Provider? To get a better idea, I am going to build a mobile webshop using Flutter and the Woocommerce package.
If I understand correctly with the Bloc pattern you have the follow:
UI screen (view)
BLOC (ViewModel, including functions such as getting data or updating data or deleting data)
Repository (Get's data from an API)
Network Provider (the api itself)
If it's not complete, feel free to add an extra explanation.
Hope anyone has clear answers!
Cheers
When implementing the Bloc pattern, is it that you already implemented state management?
Yes indeed.
Does this (in most cases) mean that I do not need to use another tool like Redux or Provider?
You can use them, but personally, I see no need when I already use BLoC and would not mix them.
Yes bloc itself is a state management tool in flutter and there is no need to use any other state management tools along with it.
Though it can be done but try to use single state management for whole app so that mismatch doesnot happen .
Also Bloc makes sure to preserve the state and update it when necessary. That is what state management is !
I was wondering what is the exact application of UseCase in Clean Architecture. Since, nowadays when you have a remote data source or rest API, the heavy processes are done on the server-side so you don't have any logic to implement in UseCase. All logic is state management, to handle loading errors, etc. and these have to be inside state management. Am I wrong? Do you have a scenario where UseCases are needed?
BLOCs control the state of widgets. Ideally, they don't have business logic. They just use UseCases.
UseCases (or Interactors) are a business logic of application. They use entities and abstract repositories. They're needed when you want to use the same business logic in several blocs. Instead of copy paste the piece of code from the existed bloc you just make 1 UseCase and use it in all the blocs you want.
UseCase uses abstract repositories. It means that UseCase doesn't depend from data source. It could be Firestore, REST api, local database etc. UseCase just know that repository returns Entities. Business logic becomes independent from data source and easy to test.
API calls are made in repository implementations. For example, we have abstract class "Repository" and it's implementations: "FirebaseRepository", "ApiRepository", "LocalRepository" etc. Thanks by polymorpthysm we can create UseCases and give them these repository implementations via constructors. It's recommended to use dependency injector like get_it.
Bloc doesn't contain any business logic. In Clean Architecture terms bloc = controller + presenter. Bloc just uses UseCases and business logic can be reused between several blocs.
Imho even though there is hardly any logic to implement in UseCase, for example just passing params. Creating useCase will allow us freely change the repository based on our needs. For example, different apps use different logic in the repository.
Clean Architecture benefit is not only about layering logic, but how to increase reusability, testability, and scalability (easier to change and modify in the future)
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
Currently am working on Sport Event Scoring app.
The structure of the app goes something like this:
Right now I am trying to include state management using provider package.
Scoring occurs at the very bottom of the Widget tree using a counter and each Widget initializes respectively named model based on a user input on the go - creating Event, adding divisions and players each happens in a dialog.
I know I need to create a provider for list of Events, however, I am not sure how to go about structuring rest of the state management. So far I tried turning each model into a Provider by mixin in the ChangeNotifier and moving all the methods which change the data inside where the state would be managed as well with notifyListeners().
However after a lot of struggling and searching I found that it's not the best approach to manage the state inside models.
What approach would be ideal?
Should I manage the state through the Event List provider, or should I go with creating a provider for each model in a separate file? If so, how?
I am not too sure about the full scope of your project nor how far you are into it but I would highly suggest checking out the BLOC library as an alternative state management solution to simply manage the state in your case.
The learning curve is fairly low with many tutorials on how exactly to use the library alongside the fact that BLOC is much less reliant on listeners from an external persons view using the library from my experiences if that is what you are struggling with.
Here is a link to the BLOC Library
If you are still persistent to use Provider, I would suggest you create a provider for each model in a separate file for multiple reasons such as separation of concerns and ease of management of state and clarity of each different model.