pkg_state_management version: 1.4.2

Published 2025-09-03

ruud

sdk | dart flutter
repository | svn
platform | generic
status | n/a
  • Readme
  • Changelog
  • Versions

pkg_state_management

Scoped, widget-based state management inspired by provider.

graph

For ChangeNotifier based data models that can trigger updates for your UI, or just plain objects for dependency injection.

More or less backwards compatible with the provider package. While it is (still) possible to use Provider and ChangeNotifierProvider from that package, it is not recommended to do so.

If you want to provide static resources like (singleton) service clients, settings or otherwise, use a service locator like GetIt.

pkg_state_management

Model

Models must all extend or implement ChangeNotifier.

class Model extends ChangeNotifier {
  late Timer _timer;
  late DateTime _dateTime;

  Model() : super() {
    _timer = Timer.periodic(const Duration(seconds: 1), _ON_Timer);
  }

  DateTime get datetime => _dateTime;

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  void _ON_Timer(final Timer timer) {
    _dateTime = DateTime.now();
    notifyListeners();
  }
}

Provider

MyProvider<Model>(
  create: (final _) => Model(),
  child: ...,
),

Children will not update when the model triggers if they are not wrapped with a consumer.

MyProvider<Model>(
  create: (final _) => Model(),
  child: Text('Will not update: ${DateTime.now().toIso8601String()}'),
),

Static models

Note that when the provider is disposed, the model is also disposed (if the model is a ChangeNotifier), (unless you set shouldDispose: false) so if you construct your provider from a static resource like create: (final _) => GetIt.instance.get<Model>(), the resource is not valid anymore. Should not be a problem if the dispose happens when the application exits.

MyProvider<Model>(
  create: (final _) => GetIt.instance.get<Model>(),
  shouldDispose: false,
  child: Text('Will not update: ${DateTime.now().toIso8601String()}'),
),

Providing an interface

Providing a model through an interface will also work:

MyProvider<ISomeModelInterface>(
  create: (final _) => SomeModelImpl(),
  child: ...
),

Multiple providers

Use MyMultiProvider to provide multiple providers. The providers must not have a child widget, while the multi-provider must have one.

MyMultiProvider(
  providers: <SingleChildWidget>[
    MyProvider<Model>(
      create: (final _) => Model(),
    ),
    MyProvider<OtherModel>(
      create: (final _) => OtherModel(),
    ),
    MyProvider<ISomeModelInterface>(
      create: (final _) => SomeModelImpl(),
    ),
    ...
  ],
  child: Wrap(
    children: <Widget>[
      Text('Will not update: ${DateTime.now().toIso8601String()}'),
    ],
  ),
),

Consumer

Always update

Wrap your widget in a MyConsumer regardless of what model properties are changed:

MyConsumer<Model>(
  builder: (context, model, child) =>
    Text(DateTime.now().toIso8601String()),
),

Never update

MyConsumer<Model>(
  shouldUpdate: false,
  builder: (context, model, child) =>
    Text(DateTime.now().toIso8601String()),
),

Selector

Always update

Wrap your widget in a MySelector regardless of what model properties are changed:

MySelector<Model, void>(
  builder: (context, model, select, child) =>
    Text(DateTime.now().toIso8601String()),
),

Specific property

When a specific property changes:

MySelector<Model, DateTime>(
  select: (current) => current.datetime,
  builder: (context, model, select, child) =>
    Text(select.toIso8601String()),
),

Conditional

When a condition is applied to a selected property:

MySelector<Model, DateTime>(
  select: (current) => current.datetime,
  shouldUpdate: (previous, current) =>
      current.second.isEven,
  builder: (context, model, select, child) =>
      Text(select.toIso8601String()),
),

Records

When a select returns a record, it is advised to implement the shouldUpdate callback, because the select will always return a new object and thus the selector always triggers:

MySelector<Model, ({bool busy, bool done})>(
  select: (current) => (busy: current.busy, done: current.done),
  shouldUpdate: (previous, current) =>
      previous.busy != current.busy || previous.done != current.done,
  builder: (context, model, select, child) =>
      model.done ? Text('done') : Text(select.busy ? 'busy' : 'idle'),
),

Changelog

1.4.2 - 2025-09-03

Fixed

  • Be sure to create a provider only once.
  • Unawaited futures.

1.4.1 - 2025-07-10

Added

  • Context maybeWatch and watch (like maybeRead and read, but with update hooks).

1.4.0 - 2025-06-30

Changed

  • Provider maybeOf:context.dependOnInheritedWidgetOfExactType<_HHProvider<T>>()?.value; to maybeOf:context.getInheritedWidgetOfExactType<_HHProvider<T>>()?.value; because dependOnInheritedWidgetOfExactType registers a dependency on a particular type by calling this method, and getInheritedWidgetOfExactType does not (our consumers handle everything with listeners, not implicit updates).

1.3.9 - 2025-06-16

Added

  • A logger in the HHChangeNotifier to show notifyListeners calls in debug mode.

1.3.8 - 2025-06-12

Changed

  • Made the builder of HHConsumer optional, renders const SizedBox() if not given. This way you can handle changes in the onChange callback only, while not rendering any widget.

1.3.7 - 2025-05-28

Changed

  • Version bump from 1.3.6 to 1.3.7 (flutter_lints -> 6.0.0 (was 5.0.0)).

1.3.6 - 2025-05-16

Fixed

  • HHValuesNotifier, internal val now private.

1.3.5 - 2025-05-09

Changed

  • Refactored some construct from if value != null ? something() : otherwise() to something?.call() ?? otherwise().
  • Selectors update _previous after the notifier trigger and onChange, otherwise previous and current would always be the equal since the trigger is within a Future.microtask call.

1.3.4 - 2025-05-01

Added

  • HHValuesNotifier.

1.3.3 - 2025-04-24

Changed

  • Do not throw but log only when notifyListeners is called from within a setState call.

1.3.2 - 2025-04-12

Removed

  • material dependency.

1.3.1 - 2025-04-08

Changed

  • Always use Future<void>.microtask in consumers and selectors.

1.3.0 - 2025-04-08

Added

  • HHOptionalConsumer that renders its child only if the requested provider is available.

1.2.9 - 2025-04-05

Changed

  • Version bump from 1.2.8 to 1.2.9 (Fixed provider lints).

1.2.8 - 2025-04-04

Changed

  • Reinstated Future<void>.microtask for consumers and selectors.

1.2.7 - 2025-03-20

Changed

  • Clarified the usage of a HHSelector with records in README.md.

1.2.6 - 2025-02-20

Fixed

  • Clear notifyListenersDebounced from HHChangeNotifier when disposed.

1.2.5 - 2024-12-19

Changed

  • Version bump from 1.2.4 to 1.2.5 (Support Apple silicon (arm64)).

1.2.4 - 2024-11-05

Changed

  • HHChangeNotifier, super.notifyListeners in a microtask.
  • Moved provider create call to Provider.didChangeDependencies from Provider.initState so a provider constructor can lookup other providers by using context.read<YourProvider>() because that was not possible from initState.

1.2.3 - 2024-11-01

Changed

  • Removed SingleChildWidget export in separate library file.

1.2.2 - 2024-10-10

Changed

  • Changed all BuildContext _ parameters to BuildContext context.
  • Removed futures from notification triggers.

1.2.1 - 2024-10-08

Added

  • HHChangeNotifier::notifyListenersDebounced.

1.2.0 - 2024-09-02

Added

  • HHChangeNotifier that blocks notifications when the model is disposed.

1.1.7 - 2024-08-22

Changed

  • Version bump from 1.1.6 to 1.1.7 (SDK update 3.5.1).

1.1.6 - 2024-08-12

Added

  • pkg_core interface for IDisposable.

1.1.5 - 2024-07-09

Changed

  • Do not use context from a Builder.

1.1.4 - 2024-06-23

Changed

  • HHProvider without Builder in buildWithChild.

1.1.3 - 2024-02-01

Changed

  • Version bump from 1.1.2 to 1.1.3 (Resolve package version confusions).

1.1.2 - 2023-12-04

Fixed

  • Update state after unmount.

1.1.1 - 2023-12-01

Changed

  • Moved onChange callback to notifier function, if debounced gets triggered once.

1.1.0 - 2023-11-09

Changed

  • Removed provider dependency.

1.0.5 - 2023-10-05

Changed

  • Dispose debouncer and change handlers when a didChangeDependencies was triggered.
  • Removed microtask in consumer updaters.

1.0.4 - 2023-07-24

Changed

  • select property of HHSelector is now mandatory.
  • Providers must be present for consumers and selectors.
  • Changed dynamic internals are now typed S.

1.0.3 - 2023-07-21

Added

  • Flag to HHProvider.of and HHProvider.maybeOf to allow calling from suspicious contexts.

1.0.2 - 2023-06-27

Changed

  • Update consumers with Future.microtask.

1.0.1 - 2023-05-09

Changed

  • Triggers are now ints.

Added

  • onUpdate callbacks to consumers.

1.0.0 - 2023-04-13

Changed

  • Renamed all My to HH tokens in class names.

0.0.11 - 2023-02-28

Changed

  • Update consumer only when mounted.

0.0.10 - 2023-02-15

Changed

  • The result of the builder functions is now dynamic (not Widget), in case your builder must return for example a DataRow for a PlutoGrid.

0.0.9 - 2023-02-15

Removed

  • MyChangeNotifier.

0.0.8 - 2023-02-09

Changed

  • Version bump from 0.0.7 to 0.0.8 (Version confusion after compiler bug chaos).

0.0.7 - 2023-01-19

Added

  • MySelector4 and MyConsumer4.
  • onUpdate callback on MyConsumer.

Changed

  • Split MyConsumer into separate MySelector for conditional updating.

Fixed

  • shouldUpdate, previous on the first try should be null, otherwise we're missing the initial update.

0.0.6 - 2023-01-19

Added

  • Consumers for more than one model.

0.0.5 - 2023-01-19

Changed

  • Models are not forced to be of type ChangeNotifier anymore.

0.0.4 - 2023-01-18

Changed

  • Typos in README.md.

0.0.3 - 2023-01-18

Changed

  • Removed doc from .pubignore.

0.0.2 - 2023-01-18

Changed

  • README.md link to screenshot.

0.0.1 - 2023-01-18

Changed

  • Initial version.

1.4.2

2025-09-03 download

1.4.1

2025-07-10 download

1.4.0

2025-06-30 download

1.3.9

2025-06-16 download

1.3.8

2025-06-12 download

1.3.7

2025-05-28 download

1.3.6

2025-05-16 download

1.3.5

2025-05-09 download

1.3.3

2025-04-24 download

1.3.2

2025-04-12 download

1.2.9

2025-04-05 download

1.2.8

2025-04-04 download

1.2.7

2025-03-20 download

1.2.6

2025-02-20 download

1.2.5

2024-12-19 download

1.2.4

2024-11-05 download

1.2.3

2024-11-01 download

1.2.2

2024-10-10 download

1.2.0

2024-09-02 download

1.1.7

2024-08-22 download

1.1.6

2024-08-12 download

1.1.5

2024-07-09 download

1.1.4

2024-06-23 download

1.1.3

2024-02-01 download

1.1.2

2023-12-04 download

1.1.0

2023-11-09 download

1.0.5

2023-10-05 download

1.0.4

2023-07-24 download

1.0.2

2023-06-27 download

1.0.1

2023-05-09 download

1.0.0

2023-04-13 download

0.0.11

2023-02-28 download

0.0.10

2023-02-15 download

0.0.8

2023-02-09 download

0.0.7

2023-01-19 download

0.0.4

2023-01-18 download

0.0.3

2023-01-18 download

0.0.2

2023-01-18 download

0.0.1

2023-01-18 download