Flutter BLoC Functionallity of = adding item to list without fully rebuild list, changing a value of class instance property - flutter

Maybe my question is a nooby one, but i really try to understand how to implement the following operations:
How to add item for a list without the need of rebuilding all list.
How to update a class instance property value.
Does BLoCProvider used only once in a class?
===> I'm asking those question because i see that BLoC working with 'Equatable' and that in a the state class there is always a need to bring default value to the state we provide to the view class.
Another Question (what change the view and operate the state):
Does i need to bring always a list in order for example to update an item from the list or only changing the state+emit(in cubit) will change the state of the application, maybe it realted to BLocListener?

Related

What does the query method do in Flutter Flame game and what type is it supposed to be?

I'm trying to get the update function in Flame game to work. I have a global variable called newInstructions that's a list that gets updated by a separate function. I want the update function to check when there's a new addition to the list and call a function (populateInfo) with that list as input. After looking at some of the documentation, I've come up with what I think would be the correct code, but it keeps returning this error:
The method 'query' isn't defined by the type 'List'
I think that part of this might come from my not fully understanding what the update/query methods do. With that, what does the query method do and what type should it be? How would I go about changing my code to fix that error?
Here is the update function that I wrote:
#override
void update(double dt){
final instructions = newInstructions.query<List>();
populateInfo(instructions);
}
With that, what does the query method do and what type should it be?
query is a Flame specific method that is used on the OrderedSet in each component where the children are stored, it is used to get children of a specific type. For example to get all Player components:
children.query<Player>();
How would I go about changing my code to fix that error?
Since you want to react to when something is added the newInstructions list you shouldn't do this check in update since this method runs at least 60 times per seconds, it's better to just react once when there is a new instruction added.
This can be done in a few different ways, you could for example put the newInstructions list in a class that you then have an add method on that both adds the instruction to a list contained within the class, and also calls populateInfo. You could also wrap the list in a ChangeNotifier like this.

Riverpod Flutter: Multiple providers for one screen

I'm new to riverpod, and I want to check that I am doing things correct.
I have a screen on my Flutter app where the use inputs lots of information about a session. Like start time, end time, notes, duration, date etc etc. All this data in the end is stored in a dart complex object MySession(), will all the above properties.
My question is, in the meantime, I am creating a seerate provider for each field. Like this:
final selectedDateProvider = StateProvider((ref) => DateTime.now());
final sessionDurationMinutesProvider = StateProvider<int>((ref) => 0);
Now in the class, I call the providers like this in the build method:
selectedDate = ref.watch(selectedDateProvider);
sessionDurationMinutes = ref.watch(sessionDurationMinutesProvider);
Then I display them in the widgets.
When they are editing, I save the state like this:
ref.read(selectedDateProvider.notifier).state = datePick;
My question is, I have lots and lots of fields on this page. So I have to create lots of providers for each field. Is this the correct practise? Can I not make a customclass for all these fields, and then make one provider which will return this custom class?
On the riverpod docs it says: You should not use StateProvider if: your state is a complex object (such as a custom class, a list/map, ...)
https://riverpod.dev/docs/providers/state_provider
I hope its clear!
Thanks
You already answered your question ;)
Yes, you can.
Make a class that will store the state of all the input fields and expose it through StateProvider.
To do it effectively you will probably need a copyWith method which can be written manually or generated. One of the possible approaches is to use freezed.

How to rebuild only a spesific item in the Listview?

I have an entity object, for simplicity lets call it now Todo. I want to have a widget where I can edit multiple of these todos simultaneously, something like EditableTodoList (and this would show a list of EditableTodos).
This widget would recieve a List<Todo> and also something like Function onTodoEdited(Todo).
I am trying to use immutable data, so when an EditableTodo is being edited (and the event gets propagated to the widget which holds the EditableTodoList), I'd create a new List<Todo> which contais the updated Todo, but then EditableTodoList would rebuild with all its EditableTodos inside.
How could I optimize this, that only the relevant EditableTodo is rebuilt? I don't want to hack around with mutating the prop original List<Todo> because that hides greatly an important detail.
Background: currently the state is inside a cubit and I am context.select-ing for every EditableTodo list item the corresponding Todo in the state, this way only the edited item rebuilds. I'd like to decouple this EditableTodoList from the cubit.
Theoretically I assume its not possible, as EditableTodoList is given new properties, so it has to rebuild, and that means all subtree gets rebuilt. EditableTodo cannot be const as its prop is not a constant.
But still, what would be the most elegant way of separating EditableTodoList from the cubit? As it only needs a List<Todo> to show, it should be possible somehow to optimize the rendering of not changed Todos
You should consider how widget, element and render trees work in order to be concerned. There is a great video about Flutter's rendering mechanism. When rebuilding a tree, framework compares the two versions of widgets by using only the key and runtime type values. This means that if you change string value of the Text widget, the same render object with mutated data will be used again. New render object won't be created, which means no unnecessary rebuilds will happen on the render tree. Rebuilding the widget tree is not expensive compared to the render tree.
There is a limit on minimizing the the build scope in the ListView. ListView itself should be rebuilt in order to update an item. So you can't target a spesific item to rebuild. But items can reactively rebuild themselves (eg. an item that listens to a stream can rebuild without effecting the others). Therefore immutable collections doesn't matter in this context since the framework doesn't care the value but key and runtime type. You can either pass a completely modified list or a list with just one element changed, it will have the same effect.

Flutter - best approach to create TabledToggledButtons?

I would like my toggle buttons to be layout in a table, and not as a single row.
The number of toggle buttons is not static -
that is upon init I load a resource which contains a list of all the texts that should become the toggle buttons.
Looked at a number of approaches, each has its issues:
Create a list of ToggleButtons and a list of lists of bools to store the appropriate selected state as a data structure to divide the toggle buttons into a number of rows. The problem with this approach is in the implementation of the onPressed method - how to get a reference to the appropriate element in the list of lists of bools? Or in other words - how to get a reference to ToggleButtons object from within the onPressed method?
Use key property to pass the index of the current ToggleButtons. It is not intended for this purpose, so it is a bad practice, also again, there seems to be no straightforward way to access the key property from the onPressed method.
Extend the ToggleButtons class, and specifically override its build method. This is considered an anti-pattern in Flutter in general. Specifically In this approach, as we want all the functionality to remain the same, and change only the internal Row -> Table widget generation in the build method, it looks like we would have to duplicate all the code of this method, which is a bad idea as it might brake things as it changes in future versions of this widget
Create a table of checkbox / switch widgets as an alternative, which should work easily, but I want the look & feel of toggle buttons, not checkboxes or switches :)
I must be missing something simple!
After posting this I have a new idea :)
A table of FlatButtons! Will be probably possible to achieve similar UI to ToggleButtons. Will try it in a bit.
I would still love to hear other suggestions regarding ToggleButtons.
Try using SwitchListTile.
The entire list tile is interactive: tapping anywhere in the tile toggles the switch. Tapping and dragging the Switch also triggers the onChanged callback.
To ensure that onChanged correctly triggers, the state passed into value must be properly managed. This is typically done by invoking State.setState in onChanged to toggle the state value.
The value, onChanged, activeColor, activeThumbImage, and inactiveThumbImage properties of this widget are identical to the similarly-named properties on the Switch widget.
The title, subtitle, isThreeLine, and dense properties are like those of the same name on ListTile.
The selected property on this widget is similar to the ListTile.selected property, but the color used is that described by activeColor, if any, defaulting to the accent color of the current Theme. No effort is made to coordinate the selected state and the value state; to have the list tile appear selected when the switch is on, pass the same value to both.
The switch is shown on the right by default in left-to-right languages (i.e. in the ListTile.trailing slot) which can be changed using controlAffinity. The secondary widget is placed in the ListTile.leading slot.
To show the SwitchListTile as disabled, pass null as the onChanged callback.

Flutter issue with init and provider

I have an issue with the provider pattern, I have a solution to my problem i just wanted to check its a good method and if there a better alternates.
I am trying to update the text controllers text when they first load the widget to have the value stored in my provider state. Originally, I just created the text controller in the init and just loaded the state in the build method and set the controllers text.
This was working until i wanted to have some validation of the content that would prevent certain things being passed into the state ( for example preventing empty strings).
textController.addListener(() {
if( RULE ABOUT WHETHER TO SET STATE BASED ON TEXT){
state.textField = textController.text;
}
});
The problem arose here, as they user would delete their word and this would fail the rule. The rebuild would occur (as they had pressed a key) and the text.controller would then rebuild to what was in the state (a single letter as it failed the rule). Effectively this prevented them from deleting, which is something i want them to be able to do but for this not to update the state.
I found this library https://pub.dev/packages/after_layout which allows a method to be overridden which is called once immediately after the build.
My solution uses this by creating the text controller in the initstate.
Assigning it to the TextField in the build.
Then creating a local field that would maintain the textField widget string content.
Then in the new afterbuild method i would assign whats on the state to the variable and update the text controllers text to have this value.
Then in the text.controllers text changed listener I used my rule to only update this state if it met the rule. Therefore if they deleted content they shouldn't be able to and closed/reopened the widget the state would rebuild to still have a valid value.
Is using this library a good solution to this or is there a better technique?
---------------- EDIT
Sorry for my wordy first part. I think my main question is just how am i meant to init Controllers if the data i need has to come from the state in the build.
For example.
// This must go in the build as it requires state
myTabsController = TabController(length: myState.list.length, vsync: this);
I'm initialisng the controller every time it builds now... How am i meant to put this in the init but still access the state variables.
(I've tried using the afterFirstLayout() callback from the AfterLayoutMixin but that just causes more problems.
Feel free to ask me to clarify more.
Thanks for your help.