Ignore the observe event when an action runs on an observable - flutter

I have an observable x.
#observable
double x
Now i have an action which mutates the x
#action
double mutatex(double z){
x=z;
}
Now whenever i call the action, the respective Observer widget gets rebuilt. Is there anyway i can prevent the rebuild of the observer widget upon calling the action. i.e. action method gets called and the mutation happens but the respective observer ignores the action.

That would kinda go against the whole idea of using the Observer, Observable and Action.
You could remove the #action or #observable annotation, but if the UI is rebuilt for a different reason (like screen resize, background and resume, etc) the new result will likely show.

Related

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 Provider reinitialize model

I use MultiProvider and then create all my models. Lazy loading is enabled and as such when I open my page widget the constructor of my model is called when I call Provider.of<>(context).
This initialize my model and the model gets fresh data.
I have the following issue however, when I pop the view(widget) and revisit the view(widget) later, Provider.of<>(context) is called again, but since the model was already initialized I get the previous data from the model (This is useful because I do use this to preserve state between certain screens).
I need my model to reinitialize since I need to refresh my data and reset the page values, and since the constructor is never called again, I don't get any of these.
No matter what I do, if I call the initialize method from initState() / didChangeDependencies() it always error since I'm changing the data while the widget is building.
I'm looking for something like the following:
MyChangeNotifier variable = MyChangeNotifier();
ChangeNotifierProvider.value(
value: variable,
child: child()
)
To reinitialize my class, but from what I read this is bad and don't know where to call it.
I have no idea how to proceed and any help would be appreciated.
So I found what I was looking for in the Provider actual documentation here.
The key is to call your code that would update the UI or trigger a rebuild inside a Future.microTask(). This will only then trigger the rebuild once the future completes and not trigger the rebuild while the widget tree is still building.
#override
initState() {
super.initState();
Future.microtask(() =>
context.read<MyNotifier>(context).getMyData(); // Or in my situation initialize the page.
);
}

How does SetState() decide whether a widget needs rebuilding?

I'm trying to wrap my head around the concept of state, the setState function, and rebuilding stateful widgets. Would this code (inside a method)
setState(() {
newText="some new text";
});
behave any differently from
newText="some new text";
setState(() {});
In other words, does setState(){} only concern itself with what's inside itself, or does it pay attention to state changes anywhere inside its parent widget (or even higher than its parent on the widget tree)?
The setState((){}) rebuilds the current widget state i.e it just calls the build method if you have updated any value inside the setState((){}) or have updated before calling the setState((){}), it will behave same.
For some values which have been initialised or defined inside the build method it will not take any effect, because the setState((){}) just rebuilds the Build() method.
In your case both the setState((){}) calls will behave the same as you have already updated your required value before rebuilding the state. The setState((){}) also updates the values which are dependent on the updated variable from setState((){}) i.e depends upon the variable value which you are updating in setState((){}).
Checkout this interactivity tutorial by flutter for uses
For the setState((){}) method uses checkout this

flutter initState() vs build()?

I am confused about when to put my code in initState() compared to build() in a stateful widget. I am doing a quiz on flutter's udacity course which has this todo item, which was to move a block of code from build() to initState(). But I don't know the purpose or advantage of doing that. Why not just put all the code in build()?
Is it that build() is called only once while initState() is called on every state change?
Thank you.
This is actually the opposite.
build can be called again in many situations. Such as state change or parent rebuild.
While initState is called only one time.
build should be used only for layout. While initState is usually used for variable initialization.
It's in the comment within the build state of the link you provided.
Widget build(BuildContext context) {
// TODO: Instead of re-creating a list of Categories in every build(),
// save this as a variable inside the State object and create
// the list at initialization (in initState()).
// This way, you also don't have to pass in the list of categories to
// _buildCategoryWidgets()
final categories = <Category>[];
...
Creating Categories List in the Build State will lead to the list being created on every build. This is necessary since you only want it to be created once, so the best place to do this is in initState() since it will only be called once when the state object is created, Thereby eliminating the cost of re-creating the categories on each build.
According to flutter doc:
InitState
Called when this object is inserted into the tree.
The framework will call this method exactly once for each State object it creates.
Override this method to perform initialization that depends on the location at which this object was inserted into the tree (i.e., context) or on the widget used to configure this object (i.e., widget)
build
The framework calls this method in a number of different situations:
After calling initState.
After calling didUpdateWidget.
After receiving a call to setState.
After a dependency of this State object changes (e.g., an InheritedWidget referenced by the previous build changes).

GWT's KeyUpHandler is called multiple times instead of one

I've added a KeyUpHandler to a Button object as follows:
button.addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(final KeyUpEvent event1) {
if (event.isDownArrow()) {
counter++;
}
}
});
However, when I debug with SuperDev mode step by step, there are two calls to the onKeyUp where the initial calls has always counter's initial value (0 in this case) and second call has the latest -maintained- value of counter. The method where I added the logic of onKeyUp is also marked as synchronized. I also tried to call removeHandler() method of HandlerRegistration right after onKeyUp is called. The result was that the mentioned two calls happened after first key up event, but when I did another key up event only one more call happened and further key up events area didn't happen. I assume this is sth related with superdev mode or there is some internal overhead after the compilation. What is the correct way of adding any event handlers at GWT? Do we need to always take care of each handler by calling removeHandler() method of HandlerRegistration?
Re: your comment about multiple calls for click/mouseup/keyup
The browser "helps" for the click handler by firing it whenever any event would effectively click, either mousedown, then mouseup but no move, or various touch or keyboard events. Consider calling preventDefault() on an event you have already handled and you don't want the browser to further look at - for example, if you call this on mouseup and keyup, then those particular actions should never result in click events going off.