Flutter Inherited Widget updateShouldNotify oldWidget same as the new one? - flutter

I am trying to deep dive into inherited widget and got stuck somewhere. When i debug on updateShouldNotify method, its parameter(old widget) has same data with the new one. Also the instances are same. Due to that contition always false and my dependent widgets dont rebuild.
I put my simple code on dartpad. Can you spot the problem that i am doing?
just push the increase from profile
https://dartpad.dev/b6409e10de32b280b8938aa75364fa7b
Thanks

Related

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 .

Add AppBar actions from Scaffold children such as from Fragment.onCreateOptionsMenu in Android (using InheritedWidget)

In Android, every Fragment can partecipate in populating the options menu (aka "appBar actions", in flutter terms) of the activity, using the Fragment.onCreateOptionsMenu callback.
I would like a similar mechanism also in flutter, i.e. that some widgets are able to add buttons ("actions") to the AppBar.
Threads had already been opened on this topic, but none reports a fully functional example and contains solutions to the precise technical problem I encountered.
To do this, I had thought of using the following 'typical' structure:
a StatefulWidget -to which I have given name ScaffoldHandler (ScaffoldHandlerWidget/ScaffoldHandlerState)- which wraps the entire Scaffold, and which uses InheritedWidget so that widgets further down the widgets tree can get a reference to it in an optimal way (using the classic of() method which executes dependOnInheritedWidgetOfExactType()).
ScaffoldHandlerState keeps in a field the actions set by the various children, and supplies them to the app-bar.
a widget that creates the AppBar. In the build() method it gets the actions to be displayed calling ScaffoldHandlerState.of().
mixin ScaffoldChild on State, which applied to a widget gives it the ability to add actions to ScaffoldHandlerState.
Internally, ScaffoldChild executes ScaffoldHandlerState.of() in didChangeDependencies() (to add actions) and in deactivate() (to remove them).
I originally used initState() and dispose() but this did not handle the case where a ScaffoldChild changes position while not being permanently removed from the widgets tree.
The problem I encountered is that ScaffoldAppBar.build is executed before ScaffoldChild.didChangeDependencies, so when the app-bar is created, ScaffoldChild still has to put its actions in ScaffoldHandlerState.
The curious thing is that this problem is due to the simple linear order in which ScaffoldAppBar and ScaffoldChild are inserted in the page: if instead of a top app-bar I want to create a bottom app-bar, the problem is not there because ScaffoldChild.didChangeDependencies would run before ScaffoldAppBar.build.
As a workaround to overcome the problem, I have inserted in ScaffoldChild.didChangeDependencies a call to scaffoldHandler.setState scheduled by WidgetsBinding.instance.addPostFrameCallback(): thus, after the actions have been inserted in ScaffoldHandler, the app-bar is updated with the new actions.
However, this solution seems like a hack to me.
In stackoverflow I see a lot of problems solved with addPostFrameCallback + setState, and sometimes that solution avoids really understanding where it goes wrong; I am interested in understanding if there are better solutions because my purpose, as well as practical, was to better understand the lifecycle of widgets.
Is there a better solution?
This is my code:
DartPad or Gist
(I tried to shorten it as much as possible, but sorry if it's not really short)

Provider - Selector rebuild when scrolling

I am using the Selector widget as shown below
Nothing wrong with it's build method, only call it when the value changes.
But when I use Devtools or android studio to track widget rebuild it's showing that the Selector it self rebuild when I am scrolling whether in a list or any other widget that support scrolling.
Yes the Selector didn't call the build method until the value changes but is this normal ?
Using Devtools:
As you can see the others (2) Selectors doesn't have to be triggers but yet they are.
sorry for my bad English, I can explain in another way in the comment section if you didn't understand me and thanks in advance.
edit:
I guess I know why the selector is rebuilding it's self, because I am using the provider class as listener to scroll controller direction with changenotifier.
here the code
in provider class:
bool isHideHomeScreenTabBar = false;
void hideShowTabBar(ScrollDirection scrollDirection) {
isHideHomeScreenTabBar = scrollDirection == ScrollDirection.reverse;
notifyListeners();
}
in my Home screen:
_scrollController.addListener(() {
Provider.of<AppProvider>(context, listen: false).hideShowTabBar(
_scrollController.position.userScrollDirection);
});
So basically the provider trigger changenotifier with every scroll I do and the selector get notified and rebuild it's self but if the value didn't change the selector won't trigger the build method (so it works fine for the child and the widget in the build method of the selector).
But even so is this normal ? and why, The other selectors aren't even listening to the scroll direction.
Anyway I found an alternative way to do this (with an animation controller) but it would be nice if someone could explain what is happening here, it's important for me at least because I might use another state management.
I know what was happing.
I am using 1 class for the provider that contains all the values I need with many methods using notifyListeners, however I thought it's ok to use 1 provider class if I use Selector for every value I had so anything that need rebuild will only rebuild when it's need it.
The problem with this approach is that with every notifyListeners call every selector got notified and rebuild it self (in my case when any scrolling detected) but the selector doesn't call the builder if the value not changed.
The fix is to make some condition that check the old value and the new value before calling notifyListeners, that works prefect in my case, this decrease the rebuilding happing when I scroll to only 1 as it's intended to be, however the other selectors in the same class also rebuild (I guess because they are all in the same class so every notifyListeners call effect them).
At the end if you end up with similar issue it is better to use ProxyProvider or any way that let you use multiple providres, beside the benefit of a better project architecture and disposing it is way better to have more control over the state.
Thanks to RĂ©mi Rousselet Riverpod it's way better than ProxyProvider and I am using it and it's awesome so consider Riverpod if you want to use ProxyProvider.

One page, multiple contexts ? Is that possible?

Here is my problem: I have an app that has 2 list view.builders. You can imagine the scenario.
within the Stateful widget, we have:
Widget build(ct)
{
and this returns a column widget that has TWO list views.
The problem I have is that one list view changes (or should change) the items in another list view.
So what are my options? To create two Widget build(ct1) and Widget build(ct2)??
Do we do that? How can I communicate changes to ct1?
Oh my goodness, I've tried a lot, even setState etc... nothing works.. Perhaps could someone tell me how I can invoke the page to be refreshed?? That would work.
I keep on finding the answers myself - but for anyone who has this issue, Flutter apparently has evolved... if you are using the latest version, I really believe that SetState() function should work for you.. you just need to use it in the right place.

When does my class need a build() method?

I understand the general approach to building UI layouts using Flutter. However, I'm still unclear which classes or UI widgets require a .build() method when I'm creating my own vs. using the defaults generated by the project.
I haven't found a clear explanation yet - even in the Flutter tutorials. They all seem to just gloss over how "the build method takes a BuildContext" and then go on to the next subject without explaining further.
Does anyone have a succinct explanation of the build method and when it is or isn't needed? And more specifically: what does it actually do?
build() method describes the part of the user interface represented by this widget.
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).
After calling deactivate and then reinserting the State object into the tree at another location.
You can find more Here
TLDR: The build methode is used to create a new widget tree by placing the Widget reurned in the page tree. This method is essentially called when you create or update the widget (by calling setState((){})