Git Product home page Git Product logo

flutter-provide's Introduction

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.

To be clear, this package will always be available at pub.dev/packages/provide — pub doesn't allow packages to "disappear". But the package likely won't be upgraded.

See Issue #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<T> - Widget used to obtain values from a ProviderNode higher up in the widget tree and rebuild on change. The Provide<T> widget should only be used with Streams or Listenables. Equivalent to ScopedModelDescendant in ScopedModel.

  • Provide.value<T> - 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<T> - 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<T> - 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:

/// 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<int> 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<Counter> creates a widget that rebuilds on change
  // - Provide.value<Counter> obtains the value directly
  // - Provide.stream<Counter> 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<Counter>(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<Counter>(
        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<Counter>(
          initialData: currentCounter,
          stream: Provide.stream<Counter>(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<Counter>` 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 InheritedWidgets 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 Types to Providers. 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 Providers. 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 ProviderNodes without listening to changes directly.

Useful widgets to use with Provider

  • ChangeNotifier — Easy way to implement Listenable. The equivalent of Model from ScopedModel.

  • ValueNotifier — Wrapping your mutable state in ValueNotifier<T> can save you from missing notifyListener calls.

  • StreamBuilder — Can be used with Provide.stream to have widgets that rebuild on stream changes.

flutter-provide's People

Contributors

filiph avatar jiaeric avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flutter-provide's Issues

Build fail: Provider.stream(Stream, {}) conflicts to Provider.stream(BuildContext)

Build log

Compiler message:
file:///Users/sunbreak/lib/flutter/.pub-cache/hosted/pub.flutter-io.cn/provide-1.0.1/lib/provide.dart:220:11: Error: Can't declare a member that conflicts with an inherited one.
  factory Provider.stream(Stream<T> stream, {T initialValue}) =>
          ^
file:///Users/sunbreak/lib/flutter/.pub-cache/hosted/pub.flutter-io.cn/provide-1.0.1/lib/provide.dart:192:13: Context: This is the inherited member.
  Stream<T> stream(BuildContext context);
            ^
Compiler terminated unexpectedly.

Reproduce

  • flutter create hello
  • add "provide ^1.0.1" to dependencies in pubspec.yaml
  • add "import 'package:provide/provide.dart';" to main.dart
  • flutter build apk --release/debug OR flutter build ios --release/debug --no-codesign

Flutter Doctor

bogon:~ sunbreak$ flutter doctor -v
[✓] Flutter (Channel stable, v1.0.0, on Mac OS X 10.14.3 18D109, locale en-CN)
• Flutter version 1.0.0 at /Users/sunbreak/lib/flutter
• Framework revision 5391447fae (3 months ago), 2018-11-29 19:41:26 -0800
• Engine revision 7375a0f414
• Dart version 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)

[!] Android toolchain - develop for Android devices (Android SDK 28.0.3)
• Android SDK at /Users/sunbreak/lib/android-sdk-macosx
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-28, build-tools 28.0.3
• ANDROID_HOME = /Users/sunbreak/lib/android-sdk-macosx
• Java binary at: /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/bin/java
• Java version Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses

[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 10.1, Build version 10B61
• ios-deploy 1.9.4
• CocoaPods version 1.5.3

[!] Android Studio (version 3.3.1)
• Android Studio at /Users/sunbreak/Applications/JetBrains Toolbox/Android Studio.app/Contents
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
✗ Unable to find bundled Java version.
• Try updating or re-installing Android Studio.

[✓] IntelliJ IDEA Ultimate Edition (version 2018.3.4)
• IntelliJ at /Users/sunbreak/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
• Flutter plugin version 33.1.2
• Dart plugin version 183.5901

[✓] VS Code (version 1.31.0)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 2.23.0

[✓] Connected device (1 available)
• sunbreak-iPhoneX • fea92a66dcc76d390a73c235d7de105436174b38 • ios • iOS 12.1.2

! Doctor found issues in 2 categories.

How can I push a new page without buildContext?

In Redux I can use navigatorKey.currentState.pushNamed('/someRoute'); to push a new page with out pass the context.
How can I do the same thing in flutter-provide?

example:
I want to push the Login Page in my SomeNetwork.dart When get a response with status_code = 401.

Is this a duplicate of "provider"?

👋 maintainer of provider here

It seems that this library aims at doing exactly what mine does: a set of generic providers to replace Inheritedwidget.

The main selling point of flutter-provide seem to be able to use multiple providers at once; which is already supported by provider through MultiProvider

What is the reasoning by creating a new one?

About operator priority problem

Explain:
'||' > '??' Actually,
so 'parent?.updateShouldNotify(oldWidget.parent) ??
false || providers != oldWidget.providers' equals 'parent?.updateShouldNotify(oldWidget.parent) ??
providers != oldWidget.providers'

Suggestion:
change
"@OverRide
bool updateShouldNotify(_InheritedProviders oldWidget) {
return parent?.updateShouldNotify(oldWidget.parent) ??
false || providers != oldWidget.providers;
}"
to
"@OverRide
bool updateShouldNotify(_InheritedProviders oldWidget) {
return providers != oldWidget.providers ? true : (parent ?.updateShouldNotify(oldWidget.parent) ?? false);
}

provider is Listenable

when I see Provide.dart ,In the 276 line ,
listenable = _getListenable(provider, value); I jump this method,
Listenable _getListenable(Provider provider, dynamic value) =>provider is Listenable ? provider : value is Listenable ? value : null;
I want to konw ,this provider when to extend Listenable?

How to use multi values of provider in one Widget?

For example: in the code below, how to use counter and switcher in one widget?
Neither Provide.value<T> or StreamBuilder<T> seems to be fited for this.

  var counter = Counter();
  var switcher = Switcher();

  var providers = Providers();

  providers
    ..provide(Provider<Counter>.value(counter))
    ..provide(Provider<Switcher>.value(switcher));

  runApp(
    ProviderNode(
        child: MyApp(), 
        providers: providers)
    );

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.