I have just started trying Flutter today. I am following the official tutorial: https://flutter.dev/docs/development/ui/interactive (this question involves Step #3)
I understand the idea of Stateful Widgets and the need for setState(), but I dont understand the point of its parameter (function). Why should we pass a function to it? Couldnt setState be parameterless and we then would simply put the state changing code (that we would put on that parameter function) right before calling setState?
So basically my question is: what is the difference between
A) setState(() { myCounter++; });
and
B) myCounter++; setState( () {} );
?
Obs: on the tutorial I linked above if I do it either way the result is (or seems to be) the same.
The callback function is there to ensure that the changes you made to the models are synchronous and you should only set the things that you UI needs.
This will ensure that the changes are set before the framework refresh the UI because you can't do async work on the callback and the result can be predictable.
If you have to do heavy computations you should do it before call setState.
In your example, it is the same because is just a simple variable increment, but in practice, if you have heavy operations or async operations and want running those. inside the callback can have a performance impact if allowed.
Check the oficinal documentation for more examples: https://api.flutter.dev/flutter/widgets/State/setState.html
I have the same doubt, I checked the code of setState and still could not find any special usage for method parameter. So I think the design of setState method parameter is not reasonable, let setState be a no parameter function is better for understanding:
myCounter++;
setState();
Related
I'm learning Flutter and recently found Microtasks. I've read up on it and I understand what Microtasks are and what the Microtask queue is, but am still a little confused why I'd ever use one.
I'd appreciate an real-world example or explanation of when/why to use a Microtask.
Thanks.
Here is a concrete example I found usefull to understand it. Some operation while the widget tree is building are forbidden. Most of the time it is used in initState
Consider you are using the provider package
initState() {
super.initState();
context.read<MyNotifier>().fetchSomething(); // -> not work
}
Actually fetchSomething() will call a http package to get data and some stuff. This is not allowed because the state update is synchronous and here there is a lap of time during the value (new/old) can change (here before and after the data loaded from http).
This could cause inconsistencies in your UI and is therefore not allowed.
A workaround is to use a microtask to achieve it. This will schedule it to happen on the next async task cycle (i.e. after build is complete here).
initState() {
super.initState();
Future.microtask(() =>
context.read<MyNotifier>().fetchSomething(someValue); --> this work
);
}
To sum up this example, Microtask is usually created if we need to complete a task later, but before returning control to the event loop.
I have seen a few different documentations refer to the term "callbacks" (Flux.jl and some SciML packages) but it is not clear what that means in the context of Julia.
I know that a callback is a function passed as an argument to another function but is there more to it than that? What would the use case for such a paradigm be?
A classic example of use of a callback is the progress bar. A callback is supplied to the function that is doing work within some kind of sequence. At regular intervals during the sequence the callback is called with some kind of information about the work being done (the percent completed in the case of the progress bar, which updates a progress display).
Flux can call a callback each time it completes a segment of training, or in the example in the source code, every 10 seconds:
https://github.com/FluxML/Flux.jl/blob/b78a27b01c9629099adb059a98657b995760b617/src/optimise/train.jl#L80-L95
As seen in https://stackoverflow.com/a/49458289/5150593, there are essentially two ways to access BuildContext after initially rendering a widget in Flutter (i.e. in initState):
Future.delayed(Duration.zero, () {
// context can be used here...
});
and
SchedulerBinding.instance.addPostFrameCallback((_) {
// context can be used here...
});
What difference is there between the two approaches? Is there any advantage to using one approach over the other? Are there any hidden side effects that I'm not seeing?
From my own exploration, if I use both methods in the same widget's initState, the order in which the callbacks are executed is the same as the order in which the callbacks are registered. I looked at the Flutter source code for Future.delayed and SchedulerBinding.instance.addPostFrameCallback but I don't really understand what's going on.
The link in the comment posted by #NBM (https://oleksandrkirichenko.com/blog/delayed-code-execution-in-flutter) pretty much answers the question. I will provide a brief explanation here for posterity.
The Future.delayed(Duration.zero, () {}) approach is using the behavior of Dart's event queue to delay execution until the next event loop iteration, at which point it is safe to access context since the widget is guaranteed to be built.
The SchedulerBinding.instance.addPostFrameCallback((_) {}); approach is specific to Flutter and is tied to the widget's lifecycle. The end effect is still to wait until the next event loop iteration, but semantically this approach makes more sense since we are solving a Flutter problem using a Flutter mechanism.
As indexWhere() searches through potentially large Lists to find the matching index, is this an async operation?
And if so is there some way to await it? e.g. similar to Future.forEach
Since the method does not return a Future but an int, then the method is synchronous:
https://api.dart.dev/stable/2.7.1/dart-core/List/indexWhere.html
I also want to point out that asynchronous code in Dart are not the same as the code is running in another thread. Since we are talking about finding a index inside a List, then you can be fairly sure that this operation can only be done in a single thread since we need to prevent modifications of the List when we are making the search.
We're testing JS apps with protractor and sometimes we get some randomly unstable tests. Sometimes the errors are Failed: stale element reference: element is not attached to the page document
Just a hunch but sometimes developers write the code like this
await element(await by.css('.pager-next')).click();
And sometimes like this
await element(by.css('.pager-next')).click();
Is either of these "more" correct? Is there any need for the inner await or does it make no difference? Could this be causing stale element reference errors?
await is only useful for functions that return a Promise. Of the three functions in your snippet, only one of them returns a Promise. (You can check what each of them returns in the Protractor api).
ElementFinder.click() returns a Promise.
element() returns an ElementFinder.
by.css() returns a ProtractorLocator.
Therefore, the only call that should have await on it is click(), which you have done correctly in your second snippet.
StaleElementReferenceException is typically caused when you keep a reference to an object that has been removed from the page, e.g. using ElementFinder.getWebElement(). This removal can be subtle sometimes. For example, Angular will sometimes invisibly remove an element from the DOM and quickly replace it with an identical-looking one. It's hard to tell that anything even changed, but from Webdriver's perspective, the element it had a reference to has disappeared.
I think a better practice would be not to be write locators like that. I'd leave awaits for functions involving the element.
I would have a locator written like this:
const myElement = element(by.css('.pager-next'));
And then using async/await in a function:
let clickMyElement = async function(){
await myElement.click();
};