stream builder vs Bloc with event - flutter

the question is why we use Bloc with streams and bloc builder not streams and stream builder only ?
and i want to know can i use stream builder with stateless widget ? and stream builder` rebuild all build method or the widget that wrap it only?
and can i use bloc builder in stateless widget when i use controller ? if yes when should i close the controller ?
BlocBuilder<BlocA, BlocAState>(
builder: (context, state) {
// return widget here based on BlocA's state
}
)```

First, I want you to read this from the bloc documentation.
BlocBuilder is very similar to StreamBuilder but has a more simple API to reduce the amount of boilerplate code needed.
The StreamBuilder is based on Stream, and the BlocBuilder` is based on cubits and blocs which are similar to screens.
But the main goal of using the Bloc library in the first place is to achieve the BloC (Business Logic Component ) pattern which separates your project into layers, the presentation, business logic, and data layers.
This bloc library makes your project follows the BlocC pattern and no layer should know about the other, this will make your project more clean and maintainable to work with, edit, upgrade, and analyze...
Using StreamBuilder, all it can do is listen to a Stream, and build a widget-sub tree based on it as an example, your project logic will be inside your view, and in another place, there is the data layer, which leads to an absolute mess, now just imagine if you have an intermediate or big flutter project, and you wanted to change just the name of a method in some file, I'm pretty sure you will get lost before you will find it because your project does not follow any architecture.
using the BlocBuilder will give you same rebuilding functionalities as StreamBuilder, but your project will be well architectures and everything is organized, the presentation/view layer will now nothing about your logic and so on for the data layer.

Related

How to allow Flutter "nested" state management?

In short, I have three levels of ChangeNotifiers, the top level, intermediary level and bottom level. Naturally, bottom level is dependent on intermediary level and the latter dependent on the top level.
My questions are:
Is it possible to achieve this using the Flutter Provider plugin?
If Yes, when using the Provider plugin, is it possible to achieve this using only ChangeNotifierProvider only?
More detailed scenario
In my Flutter application, the state is logically structured in several levels. At the top, I have the Configuration state that stores all the configurations of the app. Then, I have a DirectionState and a LocationState, both of which are dependent on the Configuration state and should be notified of changes.
Then, I have my views (UIs), that is basically structured into a Stateful widget class for encoding the logic of the UI only, and a UI model class for implementing the business logic of the UI, somewhat the state of one UI only. The latter class implements the ChangeNotifier so that the UI updates everytime its model changes. That part is pretty simple.
It becomes complex when each model's UI is dependent both on the DirectionState and a LocationState that is then dependent on the Configuration state. All UI's model should be able to change the Configuration state that should then have all effect on the entire tree. Similarly, a change in both the Direction state and Location state should affect all UI's model and ultimately the UI themselves.
With the Provider package a Provider widget will provide to all of it's children an object (we can call it a state).
With context.read<MyType>() you can retrieve the value of one of your providers.
Also calling context.watch<MyType>() inside a build method will rebuild your widget when the provider changes.
In your case we can image this structure:
Provider(
create: (_) => Configuration(),
child: Provider(
create: (_) => DirectionState(),
child: Provider(
create: (_) => LocationState(),
child: ...
)
)
)
Also you should check the Bloc library witch make the state management easier than the Provider library. (Bloc is based on the Provider package)

Best Practice for shared state between blocs in Flutter

I am new to bloc and I found that whenever I am creating a new page with it's own bloc, I have to create a Loading state and ShowLoading event repeatedly. What is the best practice to avoid this? I have tried multiple ways such as BaseBloc and BaseState, which allows others bloc to inherit it but none of them work. Is there any implementation or boiler plate for this? Thank you.
when you wat to use BaseBloc you will end up with writing with a code that is not nicely written and you can not use it in the root of the widget tree.
the Bloc way from what I notice is that each bloc is related to a Page/feature and each one will have it's own loading state and that Page will respond to it's loading state, you can notice that in the documentation page under Naming Conventions
to run around that issue usually I would go to make my loading widget inside a snack bar with loader inside it, and call it each time there is a loading state. that will make it easy to change it in the future from one place or maybe you can search for some library that can do the loading for you each time you call some method from the blocs.
another idea is to wrap the root widget with a provider that will trigger a loading widget on the root top of the widget each time you call some provider method(like showLoader() ), and from inside the bloc/blocs you can call the provider method that will trigger the loading each time from anywhere, maybe this resource is helpful for that .

Where to initialize bloc?

In one of my projects, I am using flutter_bloc package.
In that example, I instantiated bloc inside didChangeDependencies(). So bloc lives during the lifecycle of a screen.
However, my colleague told me not to initialize there. He said bloc should be initialized in app.dart where It can live over the lifecycle of the app. Because, in cases where there should be multiple screens on tablet, it will break the code.
For example, I have ScreenA, ScreenB and ScreenC. you can go to ScreenB and ScreenC through ScreenA. ScreenB and ScreenC use the same bloc, and bloc is initialized sepearately in each screens. He is saying that if the requirement is to show ScreenB and ScreenC simultaneously on a tablet, it might break the code. How?
Could you suggest me what is best? Or does it depend on the usecase?
It is the best practice to initiate bloc instance during initState as it runs only once per widget lifecycle. didChangeDependencies() may be called multiple times for example if widget is moved in the widget tree or widget gets notified of InheritedWidget change, so bloc will get new instance like that and you dont want that. What your collegue is talking is more about BlocProviders scope and sure is normal practice, but for some small-usecase-bloc might be redundant. That is up to you to decide does your whole app needs to be in scope of this bloc. Keep in mind that if lazy property is not set to false, your bloc will be created with the first call to it.

How does BlocProvider.value works with added Event

What will happen if An event is added to the bloc being passed inside the BlocProvider.value?
Will the event gets added before or after i get to the page?
And Is Blocprovider.value an ideal way to avoid adding events to bloc in initState() method?
I'm trying to avoid initstate as I'm listening to Stream of data from firebase (this event need to be called only once).
I found a workaround for this,
Using the approach stated above will make the LoadProductFromStream event get called even before getting to /opening the StreamproductPage().
To avoid this a simple and efficient approach could be used instead
create a wrapper widget
create the body (the main widget to display results)
Below is an image attached to explain this
Wrapper widget is where the bloc will be created/initialized
and where LoadProductFromStream() event will be added to the bloc
In conclusion
This way we only add LoadFromStream() event to bloc when we get to StreamproductPage
Takeaway
BlocProvider(create:(context)=> xyzBloc()) // can automatically close bloc
while
BlocProvider.value() // doesn't close bloc automatically
(i stand to be corrected)

Flutter BLoC: managing the state of primary data types

I am developing a mobile application using Flutter. I am new to Flutter. I am using BLoC for state management. I know that it is specially designed for management async execution. But also the purpose of BLoC is for state management. But I am a little bit confused and not quite sure how to handle the primary data types in BLoC.
Let's imaging the I have a button and an image. The functionality would be that when the button is clicked, the visibility of the image will be toggled. Literally, we just need to use a boolean variable to manage the state of the image. This is how I would implement it.
I have a bloc class called HomeBloc with the following implementation.
class HomeBloc {
bool _isImageDisplayed = true;
bool get isImageDisplayed => _isImageDisplayed;
void set isImageDisplayed(bool displayed) {
this._isImageDisplayed = displayed;
}
//the rest of the code for other functionalities goes here
}
final homeBloc = HomeBloc();
Then in the HomePage widget, I update the state of the image like this inside the setState method when the button is clicked.
this.setState(() {
homeBloc.isImageDisplayed = false;
});
My question is that "is it the standard way to manage primary data type in the BLoC in Flutter"? Is this the best practice? Do we need to use StreamBuilder? Do we even need to manage it inside the BLoC?
It's not the best practice I guess, as using setState becomes really hard on big applications and re-rendering widgets that don't change for no reason. Imagine making an e-commerce app and you just go to the product page, you add the product you like into the cart, but you have designed in your home page a cart icon with a red dot with a number inside it to specify how much products you got in your cart, so you handle the state of that icon in the main.dart file by passing a function that setState the home page route or maybe the whole application, it's hard, isn't it?.
Thankfully, BLoC and Provider patterns are basically using setState but in a better way so you don't have to re-render the whole page just for a small change in a text or something else, but you just re-render a specific widget in your widget tree.
I also recommend using BLoC Provider which is built on Provider and RxDart (Streams) as it makes great isolation between UI code and business code.
Check Provider and BLoC Provider.