Skip to content

Instantly share code, notes, and snippets.

@michael-wang
Last active January 16, 2024 05:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michael-wang/b7fe817b2e335f498e8c67c21cd78299 to your computer and use it in GitHub Desktop.
Save michael-wang/b7fe817b2e335f498e8c67c21cd78299 to your computer and use it in GitHub Desktop.
[Dart] Multi-value notifier & consumer
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
class MultiValueNotifier<E extends Enum, T> extends ChangeNotifier {
// Map of name to value.
final values = <E, T>{};
add(E name, T value) {
values[name] = value;
notifyListeners();
}
remove(E name) {
if (values.remove(name) != null) {
notifyListeners();
}
}
get(E name) => values[name];
}
class ValueConsumer<E extends Enum, T>
extends Selector<MultiValueNotifier<E, T>, T> {
ValueConsumer({
Key? key,
required E name,
required ValueWidgetBuilder<T> builder,
ShouldRebuild<T>? shouldRebuild,
Widget? child,
}) : super(
key: key,
shouldRebuild: shouldRebuild,
builder: builder,
selector: (_, notifier) => notifier.get(name),
child: child,
);
}
// Just an example, define enum for your use case.
enum Values {
one,
two;
}
// This is the class we want to have multiple instances and provide them in Providers.
class Foo {}
class MyWidget extends StatelessWidget {
final notifier = MultiValueNotifier<Values, Foo>();
@override
Widget build(BuildContext context) {
return MultiProvider(
providers[
ChangeNotifierProvider<MultiValueNotifier<Values, Foo>>.value(value: notifier),
];
child: // ...
);
}
valueOneReady(Foo foo) {
notifier.add(Values.one, foo);
}
valueTwoReady(Foo foo) {
notifier.add(Values.two, foo);
}
}
class WidgetOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ValueConsumer(
name: Values.one,
builder: (context, value, child) {
// value is 'foo' from valueOneReady
// ...
}
);
}
}
class WidgetTwo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ValueConsumer(
name: Values.two,
builder: (context, value, child) {
// value is 'foo' from valueTwoReady
// ...
}
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment