toggle todos checkbox trigger build function everytime - flutter

for RiverPod official todos sample, system triggers build function whenever I toggle checkbox item, is it a correct behavior ? Won't it cause performance issue? thanks.
As I know, state management has one purpose to avoid rendering widgets so often. Please correct me if any.

if you are watching your provider inside your build method then yes it rebuilds your entire build method. but if your want your the check box to only rebuild when necessary then its either (1) separates that into another class or (2) wraps that check box with Consumer Widget. something like:
Consumer(
builder(_, ref, __){
final checkboxProvider = ref.watch(yourCheckboxProvider);
return CheckBox();
}
)

Related

How to update widget tree from another widget class - Flutter

I am facing problem to re-render the page when a variable changes in one class/widget (both parent and child widgets are stateful classes).
Here is how it goes:
I have three buttons in one class which changes a variable state (foodCategory).
int foodCategory = 0;
// down in the elevated button body - i am updating the variable
setState(() {
foodCategory = 1;});
While in the other widget, i am using this variable to perform certain actions:
for (var item in foodItems.values.elementAt(foodCategory))
GestureDetector(........ and so on...
However in the second snippet, the widget dose not know if there has been a change and it is not calling the buildcontext again...
I am not sure how to overcome this problem. I have tried valuelistenablebuilder but in vain. Maybe i dont know how to use it in the loop (i am using foodcategory as an int (iterator)).
it happned to be that i was sing valuelistenable builder in a wrong way.
It is easy. Just mark the variable and changes as valueNotifier. In my case, i needed to mark foodCategory as a valueNotifer.
Than, i needed to wrap the Widget (in my case column widget) as ValueListenableBuilder. This solved my issue.

Keep UI after emit state change Cubit Flutter

My Question: Can you keep built UI that was built by a state when another state is called?
Please correct me if I'm using the cubit pattern wrong. I have a unique example I'm trying to solve. I have the cubit set up and it's working as per documentation.
I have a screen where I have a horizontal list that is returned through cubit. Then based on the horizontal list returned if you click one of the items the cubit fetches a second list to display vertically underneath the horizontal list.
var _responseCategories = await _repository.postGetRootCategories();
emit(ShowCategories(state, _responseCategories));
var _responseCategoryItems = await _repository.postGetCategoryItems(_responseCategories[0].id);
emit(ShowCategoriesItems(state, _responseCategoryItems));
The ui has a bloc builder and processes the two states but when the one state is changed the UI for the first built state is then not there I understand why this happens but is there a way to stop it until I emit the state again. The UI decodes the states in a builder as follows:
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (state is ShowCategories) buildCategories(context, state),
state is ShowCategoriesItems
? Expanded(child: buildMenuItems(context, state))
: SizedBox.shrink(), //getMenuList(_activeSelection)),
],
);
If I'm using this wrong that's understandable I just want to know if there is a better solution to this to solve the problem as the category items are different per category and I don't need to fetch the categories every time the state changes.
The app is essentially a menu. The horizontal section is the categories of the menu 'I only need to load them once' and the vertical section is the items 'I need to load them when the user selects a category'. The items are different per category but the categories never change unless set by the server.
It seems like you have a master-detail view and your detail state is just a superset of the master-no-detail state.
You could derive your detail state from the master state and add more information to it (master-list, adding selected, details-list to the derived class) or you could just go with one state for both (master-list, selected, details-list) where some things aren't set when nothing is selected yet.
If your details view is really complicated, you could also create a whole new BLoC for it, with it's own logic and builder in the widget tree, then you can have totally different states.
But states from the same BLoC, you cannot opt to only rebuild a part of the tree below the builder.
(well, technically you can do anything, but there is no point in working around a pattern. If it does not fit, use a different one. And I think you can easily make it fit as described above)

Flutter: hide/show widget by key dynamically

How can we show/hide widget inside another widget in flutter?
I have list of question which are inside list view builder I want to hide questions on user answer selection.
if you have all equations in question[] and whether to show them in show[], you could place into listbuild
return (bool[index] ? Card(child:Text(question[index])) : Container())
This returns the card in bool is true and the empty (not displayed container) otherwise.
(I think the other answer would do the trick too)
Another option you can consider though is using the Visibility widget to wrap the "question" widget and toggle the visible property based on a bool. To make this (or the above solution) work, you'd want to update the value of this bool using e.g. setState on the method called when,as you say, "user answer selection" happens.
Of course, if you have a more complicated application it might make more sense to use Provider for state management and wrap all of this in a Consumer.

Flutter: How many is too many listeners?

I am currently making a simple POS app. As I was writing the code for adding a new item to the menu. I thought about the potential number of listeners that would be present on the page. I decided to go with multiple, individual TextFormField since the user can decide how many additional toppings they want to offer; each additional topping will have their own TextFomField to enter the relevant data. Sample Structure of the TextFormField (written inside of initState())
Each TextFormField saves its value to a variable on every focus change. My worry is that if they decide to add 5 toppings then I would have 5 active listeners. So, I would like to know what is a good limit to the number of listeners I should have and is there a better solution to my problem (instead of using focus changes).
You don't have to worry about a a couple of listeners. 5 is not a relevant number by any means. If you add listeners, make sure you dispose of them when the widget is removed.
Make sure to have this in your Widget for each FocusNode / Controller that has listeners.
#override
void dispose() {
// Clean up the controller when the widget is removed from the
// widget tree.
_nameFocusNode.dispose();
super.dispose();
}
Another way is to use the onChanged property.
You could use it like this
TextFormField(onChanged: _updateName);

what is the benefit behind provider or BLoC pattern?

We have a lot of State management solutions like providers and BLoC pattern. But, why do we need them?. why can't I create a file called 'data.dart' and import this file(data.dart) wherever i need, and make changes to the variables and objects in this file(data.dart)? Does this pattern has any downsides?
State management solutions are needed for datas that changes.
Imagine having data.dart file that has a variable
String text = 'abc';
And you have a Text() widget called TextA that takes in text variable as input.
This widget would initially display abc
now you have this function called
void changeText(){
text = 'cba';
}
how would this function tell TextA to rebuild because the value of text has already been changed?
of course you can use setState((){}); as long as the function is part of TextA,
but what if the Widget is ButtonA?
similar to StatefulWidget you can change the value using setState() to rebuild the widgets but what if you want a button in child widget that change the value in parent widget ? here you need to use provider to get full control.
Note: this is as example but it has multiple uses. you can use it with Firebase auth or cloud Firestore.