-
-
Notifications
You must be signed in to change notification settings - Fork 509
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add listen: false to Consumer #188
Comments
I don't want to promote using |
I create my If this isn't clear, please let me know and I will post a snippet. |
I still do not understand why you want |
So this is a simplification of my screen: class _MyState extends State<MyScreen> {
@override
Widget build(BuildContext context) {
return ChangeNotifierProxyProvider<FirebaseAuth, MyModel>(
builder: (context, firebaseAuth, _) => MyModel(firebaseAuth),
child: Scaffold(
appBar: AppBar(
title: Text('My App'),
),
body: SafeArea(
child: Consumer<MyModel>(
builder: (_, model, child) {
return WillPopScope(
// Intercepting the Android Back button for Page Navigation
onWillPop: () async => model.isFirst,
child: child
);
},
child: Column(
children: <Widget>[
Container(
// .....
),
Consumer<MyModel>(
builder: (context, model, child) {
// .........
},
),
],
),
),
),
),
);
}
} As you can see, |
Builder(
builder: (context) {
return WillPopScope(
onWillPop: async () => Provider.of<Model>(context, listen: false).isFirst,
);
},
); |
I thought about it, but I imagined it would be simpler to have |
Also, I remember someone telling me a while ago that |
It indeed would be simpler, but I do not want peoples to use
There's nothing wrong with |
I like this RFC, will track it, thanks. |
I'm feeling lost again. I call |
I think what he's trying to say is that he wants to avoid |
Ah that makes more sense. I did read the context but assumed he was speaking more generally. Thanks! |
Yes, it's fine for event handlers. Selector is an example of a more rebust alternative. |
But how would he use Selector in this case, as he only wants a reference to his model inside a button, so there's no value to be tracked for the Selector. |
Similarly to how #188 (comment) used Consumer, but by having the Selector return |
I like this line of thinking. I'm sure to forget including this parameter myself and may only learn later should it end up being a performance problem. It would be nice to do something more explicit.
I'll look into it, but on the surface it sounds like more work and more code than simply adding a |
Well, but then the Selector will rebuild the button each time |
The issue is more about ChangeNotifier than Provider.of https://gist.github.com/rrousselGit/4910f3125e41600df3c2577e26967c91 This provider, using ValueNotifier instead of ChangeNotifier, do not suffer from this issue and do not need Selector/listen:false |
IMHO seems more complicated than just using Maybe there could be a Provider named accordingly, so this behavior would be more explicit, like |
Or |
The sense of |
Yes, but having to type But I agree that when I was reading about Provider I got a bit confused that it Provided values and also Rebuild the widget, by its name I only thought about it as a DI mechanism, maybe the names could indicate those behaviors as well and avoid all those little bugs. |
It listens by default, because not listening is more dangerous than listening. It's better to have an extra rebuild than a missing rebuild. Especially considering that rebuilding is fast and no-op |
I'm now thinking that having a special |
I meant it as a |
|
I love the |
Actually, I think Then later came Maybe @rrousselGit any thoughts on this? Maybe you already thought about it on the past? |
I'd assume
I think we have different definitions of "sane." Mind you, you've just proposed a complex per-model way to avoid having to add |
@rrousselGit I think what we are trying to propose is a way for the library to easilly deal with those cases, specially for beginners, and your solution is not an addition to the library, but to our client code. |
With is, we can write codes that are statically correct but incorrect at runtime. This defeats the whole point of reactive/declarative programming. For example, there's nothing preventing you to do: return Text(Provider.of<String>(context, listen: false)); but it is obviously undesired. If it was possible to infer it, I'd remove the My dream is |
IMO that's a lot less complex than
The boilerplate is boring. But that's only because of If I converted the same code to the ValueNotifier architecture I mentioned previously https://gist.github.com/rrousselGit/4910f3125e41600df3c2577e26967c91 (which uses the same principle), we'd have: class Counter extends ValueNotifier<int> {
Counter(): super(0);
void increment() => value++;
} With the following provider: StoreProvider<Counter, int>(
builder: (_) => Counter(),
child: MyApp(),
) And the consumers: RaisedButton(
onPressed: Provider.of<Counter>(context).increment,
child: Text('+'),
); and: Text(Provider.of<int>(context).toString()); |
Okay @rrousselGit, I think I'm understanding you now. You're agreeing that I like your The developer also has to do more work in the |
No its not needed anymore |
Oh wait! In your example, you can't message via I think I'm following now! That is pretty elegant. |
Indeed. There's also no need for notifyListeners anymore. Just assigning But this requires immutable data, which implicitly requires a code generator for the copyWith and stuff |
So let's say I want to expose multiple values from the same object. Maybe I have a record of lots of fields I'm displaying on the screen. I could make a provider for each field, but that would get tedious. So instead I define a separate class for the record -- The dev doesn't have to do that under the current paradigm, but it might be a better separation of concerns forcing the dev to do this. I am not fond of code generators. When searching for a state management solution, I rejected those that generated code without further thought. In my experience they increase the maintenance burden -- keeping generated code properly in sync. |
I'm fine with code generators. They are built in Flutter now, and there's a package that makes a test that fails if the generated sources needs to be updated |
Code generators are fine when they occur under the hood and there is never a need for me to look at the code, much less know it was generated. That usually means the code is not mirroring my code elsewhere (unless of course it's transpiled). |
I think meantime, I'm going to make myself an |
I hope that dart will increase its support of immutable class. That should remove the need for code generators. As for your NoRebuildConsumer, it's indeed more logical on its own for now. It's pretty straight forward anyway. It's just a |
IMHO |
And the |
Oh absolutely! But only with the present documentation. I'm proposing to revise the README. I've proposed diagrams for explaining the architecture of this package. They introduce the binding language (that Remi suggested). Here's a summary of the architecture using this proposed language. Scroll up for various versions of the diagrams. (These diagrams are the ones I'm currently preferring.) |
Diagrams are not my thing, I rather simple explanations and examples on what to do and what not to do and why. |
Fair enough. That should be in the documentation too. I'm the kind of person who needs to see the abstraction, whether visually or formally in text. |
Okay, I'm posting this question here because it seems relevant to this discussion. I'm writing an article about the provider architecture and I want to talk about the following things:
In the discussion above we came to call the last of these (3) "consumers" (e.g. Right now my diagrams and articles call both (2) and (3) consumers. |
I still don't see the value behind such a thing. |
FWIW I've opened a PR on Flutter that would depreciate This would allow Widget build(context) {
Provider.of<T>(context);
} and: Widget build(context) {
return RaisedButton(
onPressed: () {
Provider.of<T>(context);
},
);
} such that in the former scenario it'll consider |
My article describes the provider package as it exists right now. Right now, the dev has to explicitly pass I'm thinking that if your future implementation is going to fold non-rebuilding descendants into I'm looking forward to your future implementation -- one less thing for the dev to worry about. |
Well, Builder(builder: (context) {
return RaisedButton(
onPressed: () {
Provider.of<T>(context);
},
);
}); |
Ah poo. Okay, it looks like I need to distinguish (2) and (3) after all. My diagrams are a bit simpler for calling both consumers, but that use is going to get more confusing moving forward. As simple as this package is, it's been a challenge to accurately describe its architecture! |
Haha, that's because it's difficult to capture the simplicity of something into words/diagrams 😛 |
I need a word for descendants of a provider that need access to the state, regardless of whether they need to rebuild on state changes. That word is going in most of my diagrams. Perhaps "dependent widget"? The article makes the listener distinction only about halfway through.. |
The doc of provider uses descendants/dependents. It's also the name of some core methods that makes InheritedWidgets works:
|
This PR looks very interesting! |
I did encounter this problem where i need to use listen false inside consumer tree, and the answer it's quite simple.
and then use consumer as usual, it much more efficient rather than put things inside the builder of ChangeNotifierProvider (in my case). I hope this is the answer you're looking for. But if it's not than i'm sorry for misunderstanding the question. |
Sometimes I need just a
Provider.of<T>(context, listen: false)
but I can't use it since I don't have aBuilderContext
with the type I want to access (they are all in the same Widget).Consumer
usingchild
is a good solution, but not a perfect one, since thebuilder
method will execute for allProvider
updates.There are situations where we just want a value and no updates at all, but we don't have
BuilderContext
. We could just add aBuilderContext
and useProvider.of
, but it would be a lot more readable if we could just passlisten: false
to aConsumer
.The text was updated successfully, but these errors were encountered: