Git Product home page Git Product logo

robsonsilv4 / flutter_value_notifier Goto Github PK

View Code? Open in Web Editor NEW
3.0 1.0 1.0 348 KB

Flutter Widgets that make it easy to implement state management patterns.

Home Page: https://pub.dev/packages/flutter_value_notifier

License: MIT License

Kotlin 0.07% Swift 0.62% Objective-C 0.02% Dart 76.38% CMake 9.99% C++ 11.18% C 0.76% HTML 0.98%
dart dartlang flutter flutter-package library provider state state-management valuenotifier widgets

flutter_value_notifier's Introduction

Flutter Value Notifier

Pub Build Codecov Stars on Github License: MIT Follow on Twitter


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;
}

main.dart

void main() => runApp(CounterApp());

class CounterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ValueNotifierProvider(
        create: (_) => CounterNotifier(),
        child: CounterPage(),
      ),
    );
  }
}

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(),
          ),
        ],
      ),
    );
  }
}

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(),
);

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(),
);

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(),
);

then from either ChildA, or ScreenA we can retrieve NotifierA with:

// with extensions
context.read<NotifierA>();

// without extensions
ValueNotifierProvider.of<NotifierA>(context);

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);

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);

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(),
    )
  )
)

to:

MultiValueNotifierProvider(
  providers: [
    ValueNotifierProvider<NotifierA>(
      create: (_) => NotifierA(),
    ),
    ValueNotifierProvider<NotifierB>(
      create: (_) => NotifierB(),
    ),
    ValueNotifierProvider<NotifierC>(
      create: (_) => NotifierC(),
    ),
  ],
  child: ChildA(),
)

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
  }
)

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
  }
)

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
  }
)

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.
  },
)

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(),
)

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
  }
)

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(),
)

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(),
    ),
  ),
)

to:

MultiValueNotifierListener(
  listeners: [
    ValueNotifierListener<NotifierA, NotifierAState>(
      listener: (context, value) {},
    ),
    ValueNotifierListener<NotifierB, NotifierBState>(
      listener: (context, value) {},
    ),
    ValueNotifierListener<NotifierC, NotifierCState>(
      listener: (context, value) {},
    ),
  ],
  child: ChildA(),
)

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
  }
)

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
  }
)

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(),
);

then from ChildA we can retrieve the Dependency instance with:

// with extensions
context.read<DependencyA>();

// without extensions
DependencyProvider.of<DependencyA>(context)

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(),
    )
  )
)

to:

MultiDependencyProvider(
  providers: [
    DependencyProvider<DependencyA>(
      create: (_) => DependencyA(),
    ),
    DependencyProvider<DependencyB>(
      create: (_) => DependencyB(),
    ),
    DependencyProvider<DependencyC>(
      create: (_) => DependencyC(),
    ),
  ],
  child: ChildA(),
)

Dart Versions

  • Dart 2: >=2.17.0
  • Flutter 3: >=3.0.0

Maintainers

Thanks to Felix Angelov (@felangel) and all bloc library contributors.

flutter_value_notifier's People

Contributors

robsonsilv4 avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

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.