Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/google/flutter-provide
A simple framework for state management in Flutter.
https://github.com/google/flutter-provide
flutter state-management
Last synced: 4 days ago
JSON representation
A simple framework for state management in Flutter.
- Host: GitHub
- URL: https://github.com/google/flutter-provide
- Owner: google
- License: bsd-3-clause
- Archived: true
- Created: 2019-02-14T22:36:19.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2021-06-24T11:38:37.000Z (over 3 years ago)
- Last Synced: 2024-08-02T03:07:55.538Z (3 months ago)
- Topics: flutter, state-management
- Language: Dart
- Homepage: https://pub.dartlang.org/packages/provide
- Size: 72.3 KB
- Stars: 811
- Watchers: 29
- Forks: 58
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
- awesome-state - flutter-provide
README
**DEPRECATION NOTE:**
After discussion in the Flutter community over the difference between this
package, `package:provider`, and `package:scoped_model` (all with a similar,
InheritedWidget-based philosophy), we have decided to merge these efforts.The community-initiated `provider` supersedes this package, `provide`. Get `provider`
[here](https://pub.dev/packages/provider).To be clear, this package will always be available at
[pub.dev/packages/provide](https://pub.dev/packages/provide) — pub doesn't allow
packages to "disappear". But the package likely won't be upgraded.See [Issue #3](https://github.com/google/flutter-provide/issues/3) for the full
discussion.---
This package contains classes to allow the passing of data down the widget tree.
It is designed as a replacement for `ScopedModel` that allows for more
flexible handling of data types and data.## Key widgets and static methods
* `Provide` - Widget used to obtain values from a `ProviderNode` higher up
in the widget tree and rebuild on change. The `Provide` widget should
only be used with `Stream`s or `Listenable`s. Equivalent to
`ScopedModelDescendant` in `ScopedModel`.* `Provide.value` - Static method used to get a value from a `ProviderNode`
using the `BuildContext`. This will not rebuild on change. Similar to manually
writing a static `.of()` method for an `InheritedWidget`.* `Provide.stream` - Static method used to get a `Stream` from a
`ProviderNode`. Only works if either `T` is listenable, or if the
`Provider` comes from a `Stream`.* `Provider` - A class that returns a typed value on demand. Stored in
a `ProviderNode` to allow retrieval using `Provide`.* `ProviderNode` - The equivalent of the `ScopedModel` widget. Contains
`Providers` which can be found as an `InheritedWidget`.## Usage
This is a simple example of a counter app:
```dart
/// A provide widget can rebuild on changes to any class that implements
/// the listenable interface.
///
/// Here, we mixin ChangeNotifier so we don't need to manage listeners
/// ourselves.
///
/// Extending ValueNotifier would be another simple way to do this.
class Counter with ChangeNotifier {
int _value;int get value => _value;
Counter(this._value);
void increment() {
_value++;
notifyListeners();
}
}/// CounterApp which obtains a counter from the widget tree and uses it.
class CounterApp extends StatelessWidget {
// The widgets here get the value of Counter in three different
// ways.
//
// - Provide creates a widget that rebuilds on change
// - Provide.value obtains the value directly
// - Provide.stream returns a stream
@override
Widget build(BuildContext context) {
// Gets the Counter from the nearest ProviderNode that contains a Counter.
// This does not cause this widget to rebuild when the counter changes.
final currentCounter = Provide.value(context);return Column(children: [
// Simplest way to retrieve the provided value.
//
// Each time the counter changes, this will get rebuilt. This widget
// requires the value to be a Listenable or a Stream. Otherwise
Provide(
builder: (context, child, counter) => Text('${counter.value}'),
),// This widget gets the counter as a stream of changes.
// The stream is filtered so that this only rebuilds on even numbers.
StreamBuilder(
initialData: currentCounter,
stream: Provide.stream(context)
.where((counter) => counter.value % 2 == 0),
builder: (context, snapshot) =>
Text('Last even value: ${snapshot.data.value}')),// This button just needs to call a method on Counter. No need to rebuild
// it as the value of Counter changes. Therefore, we can use the value of
// `Provide.value` from above.
FlatButton(child: Text('increment'), onPressed: currentCounter.increment),Text('Another widget that does not depend on the Counter'),
]);
}
}void main() {
// The class that contains all the providers. This shouldn't change after
// being used.
//
// In this case, the Counter gets instantiated the first time someone uses
// it, and lives as a singleton after that.
final providers = Providers()
..provide(Provider.function((context) => Counter(0)));runApp(ProviderNode(
providers: providers,
child: CounterApp(),
));
}```
## How it works
Similar to `ScopedModel`, this relies on `InheritedWidget`s in order to
propagate data up and down the widget tree. However, unlike `ScopedModel`,
rather than storing a single concrete type, a `ProviderNode` contains a map of
`Type`s to `Provider`s. This means that a single node can contain any number of
providers, and that a provider of a type doesn't have to be of the exact
concrete type.Somewhere in the tree, there is a `ProviderNode`, which contains a set of
`Provider`s. When a `Provide` widget is created, it searches up the widget tree
for a `ProviderNode` that contains a provider for its requested type. It then
listens for any changes to that requested type.There are also static methods that operate on `BuildContext` that allow any
widget's build function to get data from `ProviderNode`s without listening to
changes directly.## Useful widgets to use with Provider
* [ChangeNotifier](https://docs.flutter.io/flutter/foundation/ChangeNotifier-class.html)
— Easy way to implement Listenable. The equivalent of `Model` from
`ScopedModel`.* [ValueNotifier](https://docs.flutter.io/flutter/foundation/ValueNotifier-class.html)
— Wrapping your mutable state in `ValueNotifier` can save you from
missing `notifyListener` calls.* [StreamBuilder](https://docs.flutter.io/flutter/widgets/StreamBuilder-class.html)
— Can be used with `Provide.stream` to have widgets that rebuild on
stream changes.