Last updated:
0 purchases
flutter value notifier
Widgets that make it easy to use ValueNotifier ⚡. Built to work with Flutter only!
Based on flutter_bloc from bloc library.
Usage #
Lets take a look at how to use ValueNotifierProvider to provide a CounterNotifier to a CounterPage and react to value changes with ValueNotifierBuilder.
counter_notifier.dart #
class CounterNotifier extends ValueNotifier<int> {
CounterNotifier() : super(0);
void increment() => value = value + 1;
void decrement() => value = value - 1;
}
copied to clipboard
main.dart #
void main() => runApp(CounterApp());
class CounterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ValueNotifierProvider(
create: (_) => CounterNotifier(),
child: CounterPage(),
),
);
}
}
copied to clipboard
counter_page.dart #
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: ValueNotifierBuilder<CounterNotifier, int>(
builder: (_, count) => Center(child: Text('$count')),
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () => context.read<CounterNotifier>().increment(),
),
const SizedBox(height: 4),
FloatingActionButton(
child: const Icon(Icons.remove),
onPressed: () => context.read<CounterNotifier>().decrement(),
),
],
),
);
}
}
copied to clipboard
At this point we have successfully separated our presentational layer from our business logic layer. Notice that the CounterPage widget knows nothing about what happens when a user taps the buttons. The widget simply notifies the CounterNotifier that the user has pressed either the increment or decrement button.
ValueNotifier Widgets #
ValueNotifierProvider #
ValueNotifierProvider is a Flutter widget which provides a notifier to its children via ValueNotifierProvider.of<T>(context). It is used as a dependency injection (DI) widget so that a single instance of a notifier can be provided to multiple widgets within a subtree.
In most cases, ValueNotifierProvider should be used to create new notifiers which will be made available to the rest of the subtree. In this case, since ValueNotifierProvider is responsible for creating the notifier, it will automatically handle closing it.
ValueNotifierProvider(
create: (_) => NotifierA(),
child: ChildA(),
);
copied to clipboard
By default, ValueNotifierProvider will create the notifier lazily, meaning create will get executed when the notifier is looked up via ValueNotifierProvider.of<NotifierA>(context).
To override this behavior and force create to be run immediately, lazy can be set to false.
ValueNotifierProvider(
lazy: false,
create: (_) => NotifierA(),
child: ChildA(),
);
copied to clipboard
In some cases, ValueNotifierProvider can be used to provide an existing notifier to a new portion of the widget tree. This will be most commonly used when an existing notifier needs to be made available to a new route. In this case, ValueNotifierProvider will not automatically close the notifier since it did not create it.
ValueNotifierProvider.value(
value: ValueNotifierProvider.of<NotifierA>(context),
child: ScreenA(),
);
copied to clipboard
then from either ChildA, or ScreenA we can retrieve NotifierA with:
// with extensions
context.read<NotifierA>();
// without extensions
ValueNotifierProvider.of<NotifierA>(context);
copied to clipboard
The above snippets result in a one time lookup and the widget will not be notified of changes. To retrieve the instance and subscribe to subsequent value changes use:
// with extensions
context.watch<NotifierA>();
// without extensions
ValueNotifierProvider.of<NotifierA>(context, listen: true);
copied to clipboard
In addition, context.select can be used to retrieve part of a value and react to changes only when the selected part changes.
final isPositive = context.select<CounterNotifier>((notifier) => notifier.value >= 0);
copied to clipboard
The snippet above will only rebuild if the value of the CounterNotifier changes from positive to negative or vice versa and is functionally identical to using a ValueNotifierSelector.
MultiValueNotifierProvider #
MultiValueNotifierProvider is a Flutter widget that merges multiple ValueNotifierProvider widgets into one.
MultiValueNotifierProvider improves the readability and eliminates the need to nest multiple ValueNotifierProviders.
By using MultiValueNotifierProvider we can go from:
ValueNotifierProvider<NotifierA>(
create: (_) => NotifierA(),
child: ValueNotifierProvider<NotifierB>(
create: (_) => NotifierB(),
child: ValueNotifierProvider<NotifierC>(
create: (_) => NotifierC(),
child: ChildA(),
)
)
)
copied to clipboard
to:
MultiValueNotifierProvider(
providers: [
ValueNotifierProvider<NotifierA>(
create: (_) => NotifierA(),
),
ValueNotifierProvider<NotifierB>(
create: (_) => NotifierB(),
),
ValueNotifierProvider<NotifierC>(
create: (_) => NotifierC(),
),
],
child: ChildA(),
)
copied to clipboard
ValueNotifierBuilder #
ValueNotifierBuilder is a Flutter widget which requires a ValueNotifier and a builder function. ValueNotifierBuilder handles building the widget in response to new values. ValueNotifierBuilder is very similar to ValueListenableBuilder but has a more simple API to reduce the amount of boilerplate code needed. The builder function will potentially be called many times and should be a pure function that returns a widget in response to the value.
See ValueNotifierListener if you want to "do" anything in response to value changes such as navigation, showing a dialog, etc...
If the notifier parameter is omitted, ValueNotifierBuilder will automatically perform a lookup using ValueNotifierProvider and the current BuildContext.
ValueNotifierBuilder<NotifierA, NotifierAState>(
builder: (_, value) {
// return widget here based on NotifierA's value
}
)
copied to clipboard
Only specify the notifier if you wish to provide a ValueNotifier that will be scoped to a single widget and isn't accessible via a parent ValueNotifierProvider and the current BuildContext.
ValueNotifierBuilder<NotifierA, NotifierAState>(
notifier: notifier, // provide the local ValueNotifier instance
builder: (_, value) {
// return widget here based on NotifierA's value
}
)
copied to clipboard
For fine-grained control over when the builder function is called an optional buildWhen can be provided. buildWhen takes the previous ValueNotifier value and current ValueNotifier value and returns a boolean. If buildWhen returns true, builder will be called with value and the widget will rebuild. If buildWhen returns false, builder will not be called with value and no rebuild will occur.
ValueNotifierBuilder<NotifierA, NotifierAState>(
buildWhen: (previousValue, value) {
// return true/false to determine whether or not
// to rebuild the widget with value
},
builder: (_, value) {
// return widget here based on NotifierA's value
}
)
copied to clipboard
ValueNotifierSelector #
ValueNotifierSelector is a Flutter widget which is analogous to ValueNotifierBuilder but allows developers to filter updates by selecting a new value based on the current notifier value. Unnecessary builds are prevented if the selected value does not change. The selected value must be immutable in order for ValueNotifierSelector to accurately determine whether builder should be called again.
If the notifier parameter is omitted, ValueNotifierSelector will automatically perform a lookup using ValueNotifierProvider and the current BuildContext.
ValueNotifierSelector<NotifierA, NotifierAState, SelectedState>(
selector: (value) {
// return selected value based on the provided value.
},
builder: (_, value) {
// return widget here based on the selected value.
},
)
copied to clipboard
ValueNotifierListener #
ValueNotifierListener is a Flutter widget which takes a ValueNotifierWidgetListener and an optional notifier and invokes the listener in response to value changes in the notifier. It should be used for functionality that needs to occur once per value change such as navigation, showing a SnackBar, showing a Dialog, etc...
listener is only called once for each value change (NOT including the initial value) unlike builder in ValueNotifierBuilder and is a void function.
If the notifier parameter is omitted, ValueNotifierListener will automatically perform a lookup using ValueNotifierProvider and the current BuildContext.
ValueNotifierListener<NotifierA, NotifierAState>(
listener: (context, value) {
// do stuff here based on NotifierA's value
},
child: Container(),
)
copied to clipboard
Only specify the notifier if you wish to provide a notifier that is otherwise not accessible via ValueNotifierProvider and the current BuildContext.
ValueNotifierListener<NotifierA, NotifierAState>(
notifier: notifier,
listener: (context, value) {
// do stuff here based on NotifierA's value
}
)
copied to clipboard
For fine-grained control over when the listener function is called an optional listenWhen can be provided. listenWhen takes the previous notifier value and current notifier value and returns a boolean. If listenWhen returns true, listener will be called with value. If listenWhen returns false, listener will not be called with value.
ValueNotifierListener<NotifierA, NotifierAState>(
listenWhen: (previousValue, value) {
// return true/false to determine whether or not
// to call listener with value
},
listener: (context, value) {
// do stuff here based on NotifierA's value
},
child: Container(),
)
copied to clipboard
MultiValueNotifierListener #
MultiValueNotifierListener is a Flutter widget that merges multiple ValueNotifierListener widgets into one.
MultiValueNotifierListener improves the readability and eliminates the need to nest multiple ValueNotifierListeners.
By using MultiValueNotifierListener we can go from:
ValueNotifierListener<NotifierA, NotifierAState>(
listener: (context, value) {},
child: ValueNotifierListener<NotifierB, NotifierBState>(
listener: (context, value) {},
child: ValueNotifierListener<NotifierC, NotifierCState>(
listener: (context, value) {},
child: ChildA(),
),
),
)
copied to clipboard
to:
MultiValueNotifierListener(
listeners: [
ValueNotifierListener<NotifierA, NotifierAState>(
listener: (context, value) {},
),
ValueNotifierListener<NotifierB, NotifierBState>(
listener: (context, value) {},
),
ValueNotifierListener<NotifierC, NotifierCState>(
listener: (context, value) {},
),
],
child: ChildA(),
)
copied to clipboard
ValueNotifierConsumer #
ValueNotifierConsumer exposes a builder and listener in order react to new values. ValueNotifierConsumer is analogous to a nested ValueNotifierListener and ValueNotifierBuilder but reduces the amount of boilerplate needed. ValueNotifierConsumer should only be used when it is necessary to both rebuild UI and execute other reactions to value changes in the notifier. ValueNotifierConsumer takes a required ValueNotifierWidgetBuilder and ValueNotifierWidgetListener and an optional notifier, ValueNotifierBuilderCondition, and ValueNotifierListenerCondition.
If the notifier parameter is omitted, ValueNotifierConsumer will automatically perform a lookup using
ValueNotifierProvider and the current BuildContext.
ValueNotifierConsumer<NotifierA, NotifierAState>(
listener: (context, value) {
// do stuff here based on NotifierA's value
},
builder: (_, value) {
// return widget here based on NotifierA's value
}
)
copied to clipboard
An optional listenWhen and buildWhen can be implemented for more granular control over when listener and builder are called. The listenWhen and buildWhen will be invoked on each notifier value change. They each take the previous value and current value and must return a bool which determines whether or not the builder and/or listener function will be invoked. The previous value will be initialized to the value of the notifier when the ValueNotifierConsumer is initialized. listenWhen and buildWhen are optional and if they aren't implemented, they will default to true.
ValueNotifierConsumer<NotifierA, NotifierAState>(
listenWhen: (previous, current) {
// return true/false to determine whether or not
// to invoke listener with value
},
listener: (context, value) {
// do stuff here based on NotifierA's value
},
buildWhen: (previous, current) {
// return true/false to determine whether or not
// to rebuild the widget with value
},
builder: (_, value) {
// return widget here based on NotifierA's value
}
)
copied to clipboard
DependencyProvider #
DependencyProvider is a Flutter widget which provides a dependency to its children via DependencyProvider.of<T>(context). It is used as a dependency injection (DI) widget so that a single instance of a dependency can be provided to multiple widgets within a subtree. ValueNotifierProvider should be used to provide notifier whereas DependencyProvider should only be used for dependencies.
DependencyProvider(
create: (_) => DependencyA(),
child: ChildA(),
);
copied to clipboard
then from ChildA we can retrieve the Dependency instance with:
// with extensions
context.read<DependencyA>();
// without extensions
DependencyProvider.of<DependencyA>(context)
copied to clipboard
MultiDependencyProvider #
MultiDependencyProvider is a Flutter widget that merges multiple DependencyProvider widgets into one.
MultiDependencyProvider improves the readability and eliminates the need to nest multiple DependencyProvider.
By using MultiDependencyProvider we can go from:
DependencyProvider<DependencyA>(
create: (_) => DependencyA(),
child: DependencyProvider<DependencyB>(
create: (_) => DependencyB(),
child: DependencyProvider<DependencyC>(
create: (_) => DependencyC(),
child: ChildA(),
)
)
)
copied to clipboard
to:
MultiDependencyProvider(
providers: [
DependencyProvider<DependencyA>(
create: (_) => DependencyA(),
),
DependencyProvider<DependencyB>(
create: (_) => DependencyB(),
),
DependencyProvider<DependencyC>(
create: (_) => DependencyC(),
),
],
child: ChildA(),
)
copied to clipboard
Dart Versions #
Dart 2: >=2.17.0
Flutter 3: >=3.0.0
Maintainers #
Robson Silva
Thanks to Felix Angelov (@felangel) and all bloc library contributors.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.