-
Notifications
You must be signed in to change notification settings - Fork 29.7k
feat: Added the ChangeNotifierBuilder widget #97256
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
Conversation
|
I made a PR (#91179) last year to add something similar to listenCondition to ValueListenableBuilder, but it was declined because the reviewer found it confusing that the condition was ignored at the first build. Does the |
Well, it does make sense. I would rather call it |
|
Here is an example of what can happen. Source codeclass CounterNotifier extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}class Counter1 extends StatelessWidget {
const Counter1();
@override
Widget build(BuildContext context) {
return ChangeNotifierBuilder(
changeNotifier: notifier,
listenCondition: () => notifier.count.isEven,
builder: (_, __) => Text('Even: ${notifier.count}'),
);
}
}
class Counter2 extends StatelessWidget {
const Counter2();
@override
Widget build(BuildContext context) {
return ChangeNotifierBuilder(
changeNotifier: notifier,
listenCondition: () => notifier.count.isOdd,
builder: (_, __) => Text('Odd: ${notifier.count}'),
);
}
}final notifier = CounterNotifier();
void main() {
runApp(const App());
}
class App extends StatelessWidget {
const App();
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage();
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _visible = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Counter1(),
if (_visible) ...[
const SizedBox(height: 16.0),
const Counter2(),
],
const SizedBox(height: 16.0),
ElevatedButton(
child: Text('${_visible ? 'Hide' : 'Show'} odd'),
onPressed: () {
setState(() => _visible = !_visible);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: notifier.increment,
),
);
}
} |
|
If you think that @kaboc The behaviour you're experiencing happens because you're using the same ChangeNotifier for two different things (showing even and odd numbers) so the logic may be flawed. But I agree that this may be confusing, I might remove it 🙂 |
Well, I am not strongly opinionated about it, and also am not from the Flutter team, so I don't know what they will think about it, haha |
|
I actually want the feature in both ChangeNotifierBuilder and ValueListenableBuilder, and so do some other developers, I guess, but it may be better to remove it unless there's an alternative way without the issue. Sorry for cutting in, btw. |
goderbauer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be a more limited AnimatedBuilder that instead of taking a general Listenable is limited to ChangeNotifiers. Why that limitation? What will this fix? What use cases does it enable?
|
Other than the name, I don't really understand the value of this over AnimatedBuilder. We could do |
|
I think the main hassle is indeed the confusion that the name |
I suggested it recently in #19255. I think the idea of the author of this PR is that by providing a new widget we don't have any potentially breaking change. |
|
Thank you everyone for your reviews! 🙂 I'm wrapping up a few answers here:
I think that
I see it as a sort of "generic listener" whose name may also be confusing. If you added more concrete
I wouldn't take a In my view, I think that we should give From my small view, I saw some people not knowing that a
I would really like to see together:
I don't think it's a matter of this being "the same as AnimatedBuilder" because this reasoning would also apply to Naming aside, which I think most of us agree should be changed, I would also update the documentation to sort of redirect or encourage developers to prefer using
You are referring to the For example, a change notifier for a login action might be "stopped" being listened if we detected that there is no active internet connection. In this case, the
Following the alias idea, then we could also make
and remove the widgets we currently have, but I don't really like this idea. I'd prefer keeping these 2 classes that specifically deal with a type. This is for the "builder" pattern that Flutter has and also classes may accept other members or functions in the future, being open to additions by nature. I think that the same doubts we have about the usefulness of However, for the reasons I've expressed before, I think they're good to exist to not give What do you think of my point of view? |
|
The difference between AnimatedBuilder and ValueListenableBuilder is that the callback for ValueListenableBuilder includes the value of the ValueListenable. ChangeListener, or rather, Listenable (ChangeNotifier is just an implementation of Listenable, they are in every other way equivalent) doesn't have a value, it only sends a signal. AnimatedBuilder should really have been called ListenableBuilder, I agree with that. But other than that, I don't see what ChangeNotifier does that AnimatedBuilder doesn't. |
|
Yes! I agree that the name |
|
@goderbauer and @Hixie since I understand that you lean towards the renaming idea, which of these approaches you think might be better?
Personally, I'd prefer option (1) so renaming the widget to |
|
I think given the amount of documentation (e.g. YouTube videos) that exists around the current name, it's probably best to do something like #2. In either case, adding documentation in all these places is definitely a good thing. |
|
I find the idea with the typedef really good. On the original idea of a listenCondition I would point to my functional_listener package that gives you rx like functions on ValueListeanables |
|
Closing this and creating a new one to improve the docs and add a typedef. Thanks everyone for the feedbacks! |
|
Curious where this landed, the typedef doesn't seem to exist? I think updating the documentation missed the key issue: semantically it just reads wrong. Even though When we have something like Apologies if it's already landed and I just don't see it... |

I have created the new
ChangeNotifierBuilderwidget, taking care of documenting it very well and also updating the existing documentation. May this be ok?This PR is for the #95967 issue so please read the proposal made in the Issue if you are looking for additional context.
There are no breaking changes!
Pre-launch Checklist
///).