{"id":15008663,"url":"https://github.com/robsonsilv4/flutter_value_notifier","last_synced_at":"2025-04-09T16:07:28.919Z","repository":{"id":65146451,"uuid":"582058334","full_name":"robsonsilv4/flutter_value_notifier","owner":"robsonsilv4","description":"Flutter Widgets that make it easy to implement state management patterns.","archived":false,"fork":false,"pushed_at":"2024-09-19T03:02:45.000Z","size":404,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T16:07:18.452Z","etag":null,"topics":["dart","dartlang","flutter","flutter-package","library","provider","state","state-management","valuenotifier","widgets"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/flutter_value_notifier","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robsonsilv4.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-25T13:52:15.000Z","updated_at":"2024-09-19T03:02:48.000Z","dependencies_parsed_at":"2024-10-23T00:36:02.981Z","dependency_job_id":null,"html_url":"https://github.com/robsonsilv4/flutter_value_notifier","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsonsilv4%2Fflutter_value_notifier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsonsilv4%2Fflutter_value_notifier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsonsilv4%2Fflutter_value_notifier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsonsilv4%2Fflutter_value_notifier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robsonsilv4","download_url":"https://codeload.github.com/robsonsilv4/flutter_value_notifier/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065287,"owners_count":21041871,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","dartlang","flutter","flutter-package","library","provider","state","state-management","valuenotifier","widgets"],"created_at":"2024-09-24T19:19:56.543Z","updated_at":"2025-04-09T16:07:28.893Z","avatar_url":"https://github.com/robsonsilv4.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/robsonsilv4/flutter_value_notifier/main/assets/logo.png\" height=\"100\" alt=\"Flutter Value Notifier\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://pub.dev/packages/flutter_value_notifier\"\u003e\u003cimg src=\"https://img.shields.io/pub/v/flutter_value_notifier.svg\" alt=\"Pub\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/robsonsilv4/flutter_value_notifier/actions/workflows/main.yaml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/robsonsilv4/flutter_value_notifier/main.yaml?branch=main\u0026label=build\u0026labelColor=333940\u0026logo=github\" alt=\"Build\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/robsonsilv4/flutter_value_notifier\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/robsonsilv4/flutter_value_notifier.svg?style=flat\u0026logo=github\u0026colorB=deeppink\u0026label=stars\" alt=\"Stars on Github\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License: MIT\"\u003e\u003c/a\u003e\n\n---\n\nWidgets that make it easy to use [ValueNotifier](https://api.flutter.dev/flutter/foundation/ValueNotifier-class.html) and helps to implement state management patterns in Flutter. Heavily inspired by [package:flutter_bloc](https://pub.dev/packages/flutter_bloc).\n\n## Usage\n\nLets take a look at how to use `ValueNotifierProvider` to provide a `CounterNotifier` to a `CounterPage` and react to value changes with `ValueNotifierBuilder`.\n\n### counter_notifier.dart\n\n```dart\nclass CounterNotifier extends ValueNotifier\u003cint\u003e {\n  CounterNotifier() : super(0);\n\n  void increment() =\u003e value = value + 1;\n  void decrement() =\u003e value = value - 1;\n}\n```\n\n### main.dart\n\n```dart\nvoid main() =\u003e runApp(CounterApp());\n\nclass CounterApp extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      home: ValueNotifierProvider(\n        create: (_) =\u003e CounterNotifier(),\n        child: CounterPage(),\n      ),\n    );\n  }\n}\n```\n\n### counter_page.dart\n\n```dart\nclass CounterPage extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Counter')),\n      body: ValueNotifierBuilder\u003cCounterNotifier, int\u003e(\n        builder: (_, count) =\u003e Center(child: Text('$count')),\n      ),\n      floatingActionButton: Column(\n        crossAxisAlignment: CrossAxisAlignment.end,\n        mainAxisAlignment: MainAxisAlignment.end,\n        children: [\n          FloatingActionButton(\n            child: const Icon(Icons.add),\n            onPressed: () =\u003e context.read\u003cCounterNotifier\u003e().increment(),\n          ),\n          const SizedBox(height: 4),\n          FloatingActionButton(\n            child: const Icon(Icons.remove),\n            onPressed: () =\u003e context.read\u003cCounterNotifier\u003e().decrement(),\n          ),\n        ],\n      ),\n    );\n  }\n}\n```\n\nAt 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.\n\n## ValueNotifier Widgets\n\n### ValueNotifierProvider\n\n**ValueNotifierProvider** is a Flutter widget which provides a notifier to its children via `ValueNotifierProvider.of\u003cT\u003e(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.\n\nIn 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.\n\n```dart\nValueNotifierProvider(\n  create: (_) =\u003e NotifierA(),\n  child: ChildA(),\n);\n```\n\nBy default, ValueNotifierProvider will create the notifier lazily, meaning `create` will get executed when the notifier is looked up via `ValueNotifierProvider.of\u003cNotifierA\u003e(context)`.\n\nTo override this behavior and force `create` to be run immediately, `lazy` can be set to `false`.\n\n```dart\nValueNotifierProvider(\n  lazy: false,\n  create: (_) =\u003e NotifierA(),\n  child: ChildA(),\n);\n```\n\nIn 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.\n\n```dart\nValueNotifierProvider.value(\n  value: ValueNotifierProvider.of\u003cNotifierA\u003e(context),\n  child: ScreenA(),\n);\n```\n\nthen from either `ChildA`, or `ScreenA` we can retrieve `NotifierA` with:\n\n```dart\n// with extensions\ncontext.read\u003cNotifierA\u003e();\n\n// without extensions\nValueNotifierProvider.of\u003cNotifierA\u003e(context);\n```\n\nThe 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:\n\n```dart\n// with extensions\ncontext.watch\u003cNotifierA\u003e();\n\n// without extensions\nValueNotifierProvider.of\u003cNotifierA\u003e(context, listen: true);\n```\n\nIn addition, `context.select` can be used to retrieve part of a value and react to changes only when the selected part changes.\n\n```dart\nfinal isPositive = context.select\u003cCounterNotifier\u003e((notifier) =\u003e notifier.value \u003e= 0);\n```\n\nThe 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`.\n\n### MultiValueNotifierProvider\n\n**MultiValueNotifierProvider** is a Flutter widget that merges multiple `ValueNotifierProvider` widgets into one.\n`MultiValueNotifierProvider` improves the readability and eliminates the need to nest multiple `ValueNotifierProviders`.\nBy using `MultiValueNotifierProvider` we can go from:\n\n```dart\nValueNotifierProvider\u003cNotifierA\u003e(\n  create: (_) =\u003e NotifierA(),\n  child: ValueNotifierProvider\u003cNotifierB\u003e(\n    create: (_) =\u003e NotifierB(),\n    child: ValueNotifierProvider\u003cNotifierC\u003e(\n      create: (_) =\u003e NotifierC(),\n      child: ChildA(),\n    )\n  )\n)\n```\n\nto:\n\n```dart\nMultiValueNotifierProvider(\n  providers: [\n    ValueNotifierProvider\u003cNotifierA\u003e(\n      create: (_) =\u003e NotifierA(),\n    ),\n    ValueNotifierProvider\u003cNotifierB\u003e(\n      create: (_) =\u003e NotifierB(),\n    ),\n    ValueNotifierProvider\u003cNotifierC\u003e(\n      create: (_) =\u003e NotifierC(),\n    ),\n  ],\n  child: ChildA(),\n)\n```\n\n### ValueNotifierBuilder\n\n**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](https://en.wikipedia.org/wiki/Pure_function) that returns a widget in response to the value.\n\nSee `ValueNotifierListener` if you want to \"do\" anything in response to value changes such as navigation, showing a dialog, etc...\n\nIf the `notifier` parameter is omitted, `ValueNotifierBuilder` will automatically perform a lookup using `ValueNotifierProvider` and the current `BuildContext`.\n\n```dart\nValueNotifierBuilder\u003cNotifierA, NotifierAState\u003e(\n  builder: (_, value) {\n    // return widget here based on NotifierA's value\n  }\n)\n```\n\nOnly 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`.\n\n```dart\nValueNotifierBuilder\u003cNotifierA, NotifierAState\u003e(\n  notifier: notifier, // provide the local ValueNotifier instance\n  builder: (_, value) {\n    // return widget here based on NotifierA's value\n  }\n)\n```\n\nFor 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.\n\n```dart\nValueNotifierBuilder\u003cNotifierA, NotifierAState\u003e(\n  buildWhen: (previousValue, value) {\n    // return true/false to determine whether or not\n    // to rebuild the widget with value\n  },\n  builder: (_, value) {\n    // return widget here based on NotifierA's value\n  }\n)\n```\n\n### ValueNotifierSelector\n\n**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.\n\nIf the `notifier` parameter is omitted, `ValueNotifierSelector` will automatically perform a lookup using `ValueNotifierProvider` and the current `BuildContext`.\n\n```dart\nValueNotifierSelector\u003cNotifierA, NotifierAState, SelectedState\u003e(\n  selector: (value) {\n    // return selected value based on the provided value.\n  },\n  builder: (_, value) {\n    // return widget here based on the selected value.\n  },\n)\n```\n\n### ValueNotifierListener\n\n**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...\n\n`listener` is only called once for each value change (**NOT** including the initial value) unlike `builder` in `ValueNotifierBuilder` and is a `void` function.\n\nIf the notifier parameter is omitted, `ValueNotifierListener` will automatically perform a lookup using `ValueNotifierProvider` and the current `BuildContext`.\n\n```dart\nValueNotifierListener\u003cNotifierA, NotifierAState\u003e(\n  listener: (context, value) {\n    // do stuff here based on NotifierA's value\n  },\n  child: Container(),\n)\n```\n\nOnly specify the notifier if you wish to provide a notifier that is otherwise not accessible via `ValueNotifierProvider` and the current `BuildContext`.\n\n```dart\nValueNotifierListener\u003cNotifierA, NotifierAState\u003e(\n  notifier: notifier,\n  listener: (context, value) {\n    // do stuff here based on NotifierA's value\n  }\n)\n```\n\nFor 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`.\n\n```dart\nValueNotifierListener\u003cNotifierA, NotifierAState\u003e(\n  listenWhen: (previousValue, value) {\n    // return true/false to determine whether or not\n    // to call listener with value\n  },\n  listener: (context, value) {\n    // do stuff here based on NotifierA's value\n  },\n  child: Container(),\n)\n```\n\n### MultiValueNotifierListener\n\n**MultiValueNotifierListener** is a Flutter widget that merges multiple `ValueNotifierListener` widgets into one.\n`MultiValueNotifierListener` improves the readability and eliminates the need to nest multiple `ValueNotifierListeners`.\nBy using `MultiValueNotifierListener` we can go from:\n\n```dart\nValueNotifierListener\u003cNotifierA, NotifierAState\u003e(\n  listener: (context, value) {},\n  child: ValueNotifierListener\u003cNotifierB, NotifierBState\u003e(\n    listener: (context, value) {},\n    child: ValueNotifierListener\u003cNotifierC, NotifierCState\u003e(\n      listener: (context, value) {},\n      child: ChildA(),\n    ),\n  ),\n)\n```\n\nto:\n\n```dart\nMultiValueNotifierListener(\n  listeners: [\n    ValueNotifierListener\u003cNotifierA, NotifierAState\u003e(\n      listener: (context, value) {},\n    ),\n    ValueNotifierListener\u003cNotifierB, NotifierBState\u003e(\n      listener: (context, value) {},\n    ),\n    ValueNotifierListener\u003cNotifierC, NotifierCState\u003e(\n      listener: (context, value) {},\n    ),\n  ],\n  child: ChildA(),\n)\n```\n\n### ValueNotifierConsumer\n\n**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`.\n\nIf the `notifier` parameter is omitted, `ValueNotifierConsumer` will automatically perform a lookup using\n`ValueNotifierProvider` and the current `BuildContext`.\n\n```dart\nValueNotifierConsumer\u003cNotifierA, NotifierAState\u003e(\n  listener: (context, value) {\n    // do stuff here based on NotifierA's value\n  },\n  builder: (_, value) {\n    // return widget here based on NotifierA's value\n  }\n)\n```\n\nAn 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`.\n\n```dart\nValueNotifierConsumer\u003cNotifierA, NotifierAState\u003e(\n  listenWhen: (previous, current) {\n    // return true/false to determine whether or not\n    // to invoke listener with value\n  },\n  listener: (context, value) {\n    // do stuff here based on NotifierA's value\n  },\n  buildWhen: (previous, current) {\n    // return true/false to determine whether or not\n    // to rebuild the widget with value\n  },\n  builder: (_, value) {\n    // return widget here based on NotifierA's value\n  }\n)\n```\n\n### DependencyProvider\n\n**DependencyProvider** is a Flutter widget which provides a dependency to its children via `DependencyProvider.of\u003cT\u003e(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.\n\n```dart\nDependencyProvider(\n  create: (_) =\u003e DependencyA(),\n  child: ChildA(),\n);\n```\n\nthen from `ChildA` we can retrieve the `Dependency` instance with:\n\n```dart\n// with extensions\ncontext.read\u003cDependencyA\u003e();\n\n// without extensions\nDependencyProvider.of\u003cDependencyA\u003e(context)\n```\n\n### MultiDependencyProvider\n\n**MultiDependencyProvider** is a Flutter widget that merges multiple `DependencyProvider` widgets into one.\n`MultiDependencyProvider` improves the readability and eliminates the need to nest multiple `DependencyProvider`.\nBy using `MultiDependencyProvider` we can go from:\n\n```dart\nDependencyProvider\u003cDependencyA\u003e(\n  create: (_) =\u003e DependencyA(),\n  child: DependencyProvider\u003cDependencyB\u003e(\n    create: (_) =\u003e DependencyB(),\n    child: DependencyProvider\u003cDependencyC\u003e(\n      create: (_) =\u003e DependencyC(),\n      child: ChildA(),\n    )\n  )\n)\n```\n\nto:\n\n```dart\nMultiDependencyProvider(\n  providers: [\n    DependencyProvider\u003cDependencyA\u003e(\n      create: (_) =\u003e DependencyA(),\n    ),\n    DependencyProvider\u003cDependencyB\u003e(\n      create: (_) =\u003e DependencyB(),\n    ),\n    DependencyProvider\u003cDependencyC\u003e(\n      create: (_) =\u003e DependencyC(),\n    ),\n  ],\n  child: ChildA(),\n)\n```\n\n## Dart Versions\n\n- Dart 2: \u003e=2.19.0\n- Flutter 3: \u003e=3.0.0\n\n## Maintainers\n\n- [@robsonsilv4 (Robson Silva)](https://github.com/robsonsilv4)\n\nThanks to [@felangel](https://github.com/felangel), [bloc library contributors](https://github.com/felangel/bloc/graphs/contributors) and [Icons8](https://icons8.com) by [Electricity](https://icons8.com/icon/0p9q9Fp5U2bz/electricity) icon.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobsonsilv4%2Fflutter_value_notifier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobsonsilv4%2Fflutter_value_notifier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobsonsilv4%2Fflutter_value_notifier/lists"}