Fixes an issue with FutureProvider<void>
(#2028)
- It is now correctly possible to use
ProviderSubscription
s insideConsumerState.dispose
(thanks to @1980) - Update dependencies.
- fixes an exception on newer Dart versions
- fixes an edge-case where
FutureProvider
/AsyncNotifier
did not emit the new state when the createdFuture
completed (#1997) - fixes errors inside FutureProvider/AsyncNotifier/StreamProvider not preserving the previous state (if any).
- Update dependencies.
Fix typos
A small release adding missing utilities and fixing some web related issues.
-
Added
provider.overrideWith((ref) => state
) -
Added
FutureProviderRef.future
. -
Deprecated
StateProvider.state
Instead, use eitherref.watch(stateProvider)
orref.read(stateProvider.notifier).state =
-
Deprecated
provider.overrideWithProvider
. Instead useprovider.overrideWith
-
Added
Ref.notifyListeners()
to forcibly notify dependents. This can be useful for mutable state. -
Added
@useResult
toRef.refresh
/WidgetRef.refresh
-
Added
Ref.exists
to check whether a provider is initialized or not. -
FutureProvider
,StreamProvider
andAsyncNotifierProvider
now preserve the previous data/error when going back to loading. This is done by allowingAsyncLoading
to optionally contain a value/error. -
Added
AsyncValue.when(skipLoadingOnReload: bool, skipLoadingOnRefresh: bool, skipError: bool)
flags to give fine control over whether the UI should showloading
ordata/error
cases. -
Add
AsyncValue.requireValue
, to forcibly obtain thevalue
and throw if in loading/error state -
Doing
ref.watch(futureProvider.future)
can no-longer return aSynchronousFuture
. That behavior could break variousFuture
utilities, such asFuture.wait
-
Add
AsyncValue.copyWithPrevious(..., isRefresh: false)
to differentiate rebuilds fromref.watch
vs rebuilds fromref.refresh
. -
ProviderContainer no-longer throws when disposed if it has an undisposed child ProviderContainer.
-
Improved the error message when trying to modify a provider inside a widget life-cycle.
-
Fixes a stackoverflow on Web caused by Dart (thanks to @leehack)
-
Fixes a bug when the root ProviderContainer is not associated with a ProviderScope.
-
Fixes a case where a circular dependency between providers was incorrectly allowed (#1766)
- FIX: Fixed an assert error if a
family
depends on itself while specifyingdependencies
. (#1721).
Fixed an assert error if a family
depends on itself while specifying dependencies
.
Updated changelog (see 2.0.0)
Here is the changelog for all the changes in the 2.0 version. An article is in progress and will be linked here once available.
Breaking changes:
FutureProvider.stream
is removed.- Using
overrideWithProvider
, it is no-longer possible to override a provider with a different type of provider (such as overridingFutureProvider
with aStreamProvider
). AsyncError.stackTrace
is now a required positional parameter and non-nullable- All
overrideWithValue
methods are removed, besidesProvider.overrideWithValue
. This change is temporary, and these methods will be reintroduced in a later version. In the meantime, you can useoverrideWithProvider
. - Modifiers (
provider.future
,provider.state
, ...) no-longer are providers, and therefore no-longer appear insideProviderObserver
. - The
Reader
typedef is removed. UseRef
instead. ProviderListener
is removed. Usedref.listen
instead.- Removed the deprecated
ProviderReference
. - Providers no-longer throw a
ProviderException
if an exception was thrown while building their value. Instead, they will rethrow the thrown exception and its stacktrace. - It is no longer possible to pass
provider.future/.notifier/...
to the parameterdependencies
of provider. Passing the provider directly is enough. - The
Family
type now has a single generic parameter instead of 3.
Non-breaking changes:
- Upgrade minimum required Flutter SDK version to 3.0.0
- Upgrade minimum required Dart SDK version to 2.17.0
- Added
WidgetRef.context
. This allows functions that depend on aWidgetRef
to use theBuildContext
without having to receive it as paramreter. - Added
provider.selectAsync
, which allows to both await an async value while also filtering rebuilds. - Added
WidgetRef.listenManual
for listening to providers in a widget outside ofbuild
. - Added
ref.listenSelf
, for subscribing to changes of a provider within that provider. That can be useful for logging purposes or storing the state of a provider in a DB. - Added
container.invalidate(provider)
/ref.invalidate(provider)
andref.invalidateSelf()
. These are similar toref.refresh
methods, but do not immediately rebuild the provider.
These methods are safer than ref.refresh
as they can avoid a provider
rebuilding twice in a quick succession.
-
Added
ref.onAddListener
,ref.onRemoveListener
,ref.onCancel
andref.onResume
. All of which allow performing side-effects when providers are listened or stop being listened. -
A new
AutoDisposeRef.keepAlive()
function is added. It is meant to replaceAutoDisposeRef.maintainState
to make logic for preventing the disposal of a provider more reusable. -
feat;
AutoDisposeRef.maintainState
is deprecated. Use the newAutoDisposeRef.keepAlive()
instead. -
Add support for
ref.invalidate(family)
to recompute an entire family (#1517) -
Added
AsyncValue.valueOrNull
to obtain the value while ignoring potential errors. -
Added new functionalities to
AsyncValue
:hasError
,hasData
,asError
,isLoading
,copyWithPrevious
andunwrapPrevious
.
Fixes:
- fixed a bug where
AsyncValue.whenData
did not preserveAsyncValue.isLoading/isRefreshing
StateProvider
andStateNotifierProvider
no longer notify their listeners onref.refresh
if the new result is identical to the old one.- fixed potential null exception when using
autoDispose
- fixed a bug where unmounting a nested ProviderScope could cause an exception (#1400)
- Fixed an issue where providers were incorrectly allowed to depend on themselves,
breaking
autoDispose
in the process. - Fixed a memory leak when using
StateProvider.autoDispose
's.state
- Fix
ProviderObserver.didDisposeProvider
not executing on provider refresh. - Fixed an issue where
AsyncValue.value
did not throw if there is an error. - Fixed a cast error when overriding a provider with a more specific provider type (#1100)
- Fixed a bug where
onDispose
listeners could be executed twice under certain conditions when usingautoDispose
. - Fixed an issue where refreshing a
provider.future
/provider.stream
did work properly - Fixed false positive with
ref.watch
asserts
Fix Timer leak when using cacheTime
/disposeDelay
and disposing a ProviderContainer
fix: a bug where unmounting a nested ProviderScope could cause an exception (#1400)
- Upgrade minimum required Dart SDK version to 2.17.0
- Upgrade minimum required Flutter SDK version to 3.0.0
- Added
WidgetRef.listenManual
for listening to providers in a widget outside ofbuild
. - Added
AsyncValue.valueOrNull
to obtain the value while ignoring potential errors. - Fixed an issue where
AsyncValue.value
did not throw if there is an error. - Fix families not applying cacheTime/disposeDelay
- Fixed a bug where an exception may be thrown asynchronously after a
KeepAliveLink
is cancelled.
- Fixed a bug where emitting an
AsyncData
after anAsyncError
leads toAsyncValue.hasError
to be true
-
Added
ProviderScope.parent
, a property used for manually overriding a scope's parent. This is useful for allowing modals/dialogs to access scoped providers -
Added
ref.listenSelf
, for subscribing to changes of a provider within that provider. That can be useful for logging purposes or storing the state of a provider in a DB. -
Added
disposeDelay
to allautoDispose
providers and toProviderContainer
/ProviderScope
. This configures the amount of time before a provider is disposed when it is not listened. -
Added
container.invalidate(provider)
/ref.invalidate(provider)
andref.invalidateSelf()
. These are similar toref.refresh
methods, but do not immediately rebuild the provider.These methods are safer than
ref.refresh
as they can avoid a provider rebuilding twice in a quick succession. -
The duration passed to
cacheTime
now represents the minimum amount of time after the latest change of a provider, instead of the first time a provider built. -
Fixed an issue where providers were incorrectly allowed to depend on themselves, breaking
autoDispose
in the process. -
Fixed a memory leak when using
StateProvider.autoDispose
's.state
-
Fix
ProviderObserver.didDisposeProvider
not executing on provider refresh.
When calling ref.listen
on a provider, this provider will now properly
rebuild if one of its dependency had changed.
-
Deprecated
ref.maintainState=
in favor of a newly addedref.keepAlive()
. This newref.keepAlive()
function is similar tomaintainState
but better handles cases where we have multiple logics that want to keep the state of a provider alive for some period of time. -
Removed the deprecated
ProviderReference
. -
Added
ProviderContainer.cacheTime
andMyProvider.autoDispose(..., cacheTime: duration)
.cacheTime
is used to keep anautoDispose
provider alive for at least a minimum amount of time before it gets disposed if not listened. -
Added
ref.onAddListener
,ref.onRemoveListener
,ref.onCancel
andref.onResume
. All of which allow performing side-effects when providers are listened or stop being listened.
-
Now requires Dart 2.16
-
Breaking Providers no-longer throw a
ProviderException
if an exception was thrown while building their value. Instead, they will rethrow the thrown exception and its stacktrace. -
Removed
AsyncValue
'sisError
/isData
-
Added new functionalities to
AsyncValue
:hasError
,hasData
,copyWithPrevious
-
Added
provider.selectAsync
, which allows to both await an async value while also filtering rebuilds. -
When a provider emits an
AsyncError
followed by anAsyncData
, theAsyncData
emitted will now contain the latest error/stackTrace too. -
Fixed a cast error when overriding a provider with a more specific provider type (#1100)
-
Fixed a bug where
onDispose
listeners could be executed twice under certain conditions when usingautoDispose
.
-
Breaking After a provider has emitted an
AsyncValue.data
orAsyncValue.error
, that provider will no longer emit anAsyncValue.loading
. Instead, it will re-emit the latest value, but with the propertyAsyncValue.isRefreshing
to true.This allows the UI to keep showing the previous data/error when a provider is being refreshed.
-
Adding
isLoading
,isError
,isData
andasError
toAsyncValue
. Those getters allow interacting withAsyncValue
without having to rely on pattern matching. -
Fixed an issue where refreshing a
provider.future
/provider.stream
did work properly -
Fixed false positive with
ref.watch
asserts
Removed an assert preventing from overriding the same provider/family
multiple times on a ProviderScope
/ProviderContainer
.
Fixed a null exception on web
Improved the performance of the assert which verifies that providers properly
respect their dependencies
variable.
Riverpod is now stable!
-
Breaking:
ProviderContainer.debugProviderValues
andProviderContainer.debugProviderElements
are removed. You can now instead useProviderContainer.getAllProviderElements
. -
ChangeNotifierProvider
now supports nullableChangeNotifier
(#856) -
Increased minimum SDK version to 2.14.0
-
Breaking The return value when reading a
StateProvider
changed. Before, doingref.read(someStateProvider)
would return theStateController
instance. Now, this will only return the state of theStateController
. This new behaviour matchesStateNotifierProvider
.For a simple migration, the old behavior is available by writing
ref.read(someStateProvider.state)
. -
Added
ref.listen
for triggering actions inside providers/widgets when a provider changes.It can be used to listen to another provider without recreating the provider state:
final counterProvider = StateNotifierProvider<Counter, int>(...); final anotherProvider = Provider<T>((ref) { ref.listen<int>(counterProvider, (previous, count) { print('counter changed from $previous to $count'); }); });
Alternatively, it can be used by widgets to show modals/dialogs:
final counterProvider = StateNotifierProvider<Counter, int>(...); class Example extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { ref.listen<int>(counterProvider, (previous, count) { showDialog(...); }); } }
-
ProviderListener
is deprecated in favor ofref.listen
. -
It is now possible to "await" all providers that emit an
AsyncValue
(previously limited toFutureProvider
/StreamProvider
). This includes cases where aStateNotifierProvider
exposes anAsyncValue
:class MyAsyncStateNotifier extends StateNotifier<AsyncValue<MyState>> { MyAsyncStateNotifier(): super(AsyncValue.loading()) { // TODO fetch some data and update the state when it is obtained } } final myAsyncStateNotifierProvider = StateNotifierProvider<MyAsyncStateNotifier, AsyncValue<MyState>>((ref) { return MyAsyncStateNotifier(); }); final someFutureProvider = FutureProvider((ref) async { MyState myState = await ref.watch(myAsyncStateNotifierProvider.future); });
-
Deprecated
StreamProvider.last
in favor ofStreamProvider.future
. -
StreamProvider.future
,StreamProvider.stream
andFutureProvider.future
now expose a future/stream that is independent from how many times the associated provider "rebuilt":- if a
StreamProvider
rebuild before its stream emitted any value,StreamProvider.future
will resolve with the first value of the new stream instead. - if a
FutureProvider
rebuild before its future completes,FutureProvider.future
will resolve with the result of the new future instead.
- if a
-
You can now override any provider with any other provider, as long as the value that they expose matches. For example, it is possible to override a
StreamProvider<Model>
with aProvider<AsyncValue<Model>>
. -
ref.onDispose
now calls the dispose function as soon as one of the provider's dependency is known to have changed -
Providers can now call
ref.refresh
to refresh a provider, instead of having to doref.container.refresh
. -
Providers no longer wait until their next read to recompute their state if one of their dependencies changed and they have listeners.
-
Added
ProviderContainer.pump
, a utility to easily "await" until providers notify their listeners or are disposed. -
fixed an issue when using both
family
andautoDispose
that could lead to an inconsistent state
-
useProvider
is removed in favor ofHookConsumerWidget
. Before:class Example extends HookWidget { @override Widget build(BuildContext context) { useState(...); int count = useProvider(counterProvider); ... } }
After:
class Example extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { useState(...); int count = ref.watch(counterProvider); ... } }
-
Breaking: The prototype of
ConsumerWidget
'sbuild
andConsumer
'sbuilder
changed. Before:class Example extends ConsumerWidget { @override Widget build(BuildContext context, ScopedReader watch) { int count = watch(counterProvider); ... } }
After:
class Example extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { int count = ref.watch(counterProvider); ... } }
-
ProviderListener
is deprecated. Instead, useref.listen
:class Example extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { ref.listen<int>(counter, (count) { print('count changed $count'); }); } }
-
Added
ConsumerStatefulWidget
+ConsumerState
, a variant ofStatefulWidget
s that have access to aWidgetRef
. -
All "watch" functions now support
myProvider.select((value) => ...)
. This allows filtering rebuilds:final userProvider = StateNotifierProvider<UserController, User>(...); Consumer( builder: (context, ref, _) { // With this syntax, the Consumer will not rebuild if `userProvider` // emits a new User but its "name" didn't change. bool userName = ref.watch(userProvider.select((user) => user.name)); }, )
-
ProviderReference
is deprecated in favor ofRef
. -
Breaking:
ProviderObserver.didUpdateProvider
now receives both the previous and new value. -
Breaking:
ProviderObserver.mayHaveChanged
is removed. -
Breaking:
Family.overrideWithProvider
now must create a provider:final family = Provider.family<State, Arg>(...); family.overrideWithProvider( (Arg arg) => Provider<State>((ref) => ...) );
-
All providers now receive a custom subclass of
ProviderRefBase
as a parameter:Provider<T>((ProviderRef<T> ref) {...}); FutureProvider<T>((FutureProviderRef<T> ref) {...}); StateProvider<T>((StateProviderRef<T> ref) {...});
That allows providers to implement features that is not shared with other providers.
-
Provider
,FutureProvider
andStreamProvider
'sref
now have astate
property, which represents the currently exposed value. Modifying it will notify the listeners:Provider<int>((ref) { ref.listen(onIncrementProvider, (_) { ref.state++; }); return 0; });
-
StateProvider
'sref
now has acontroller
property, which allows the provider to access theStateController
exposed.
-
-
Breaking:
ProviderReference.mounted
is removed. You can implement something similar usingonDispose
:Provider<T>((ref) { var mounted = true; ref.onDispose(() => mounted = false); });
-
Breaking:
ScopedProvider
is removed. To migrate, changeScopedProvider
s toProvider
s. -
All providers now come with an extra named parameter called
dependencies
. This parameter optionally allows defining the list of providers/families that this new provider depends on:final a = Provider(...); final b = Provider((ref) => ref.watch(a), dependencies: [a]);
By doing so, this will tell Riverpod to automatically override
b
ifa
gets overridden.
-
Breaking
AsyncValue.copyWith
is removed -
Breaking
AsyncValue.error(..., stacktrace)
is now a named parameter instead of postional parameter. -
Deprecated
AsyncValue.data
in favor ofAsyncValue.value
-
Allowed
AsyncData
,AsyncError
andAsyncLoading
to be extended -
Added
AsyncValue.whenOrNull
, similar towhenOrElse
but instead of an "orElse" parameter, returnsnull
. -
Added
AsyncValue.value
, which allows reading the value without handling loading/error states. -
AsyncError
can now be instantiated withconst
. -
Added
StateController.update
, to simplify updating the state from the previous state:final provider = StateController((ref) => 0); ... ref.read(provider).update((state) => state + 1);
-
It is no longer allowed to use
ref.watch
orref.read
inside a selector:provider.select((value) => ref.watch(something)); // KO, cannot user ref.watch inside selectors
-
FutureProvider now creates a
FutureOr<T>
instead of aFuture<T>
. That allows bypassing the loading state in the event where a value was synchronously available.
- Fixed a bug where widgets were not rebuilding in release mode under certain conditions
- FIX: StreamProvider.last no longer throws a StateError when no value were emitted (#296).
- fixed an issue where when chaining providers, widgets may re-render a frame late, potentially causing a flicker. (see #648)
Fixed an issue where dependencies
did not work for ChangeNotifierProvider
(#800)
Fixed a bug where reading a provider within a consumer could throw (#796)
Fix an issue where *Provider.autoDispose
were not able to specify the
dependencies
parameter.
-
FutureProvider now creates a
FutureOr<T>
instead of aFuture<T>
That allows bypassing the loading state in the event where a value was synchronously available. -
During loading and error states,
FutureProvider
andStreamProvider
now expose the latest value throughAsyncValue
. That allows UI to show the previous data while some new data is loading, inatead of showing a spinner:final provider = FutureProvider<User>((ref) async { ref.watch(anotherProvider); // may cause `provider` to rebuild return fetchSomething(); }) ... Widget build(context, ref) { return ref.watch(provider).when( error: (err, stack, _) => Text('error'), data: (user) => Text('Hello ${user.name}'), loading: (previous) { if (previous is AsyncData<User>) { return Text('loading ... (previous: ${previous.value.name})'}); } return CircularProgressIndicator(); } ); }
- Breaking
AsyncValue.copyWith
is removed - Breaking
AsyncValue.error(..., stacktrace)
is now a named parameter instead of postional parameter. - Breaking
AsyncValue.when(loading: )
and ``AsyncValue.when(error: )(and
when` variants) now receive an extra "previous" parameter. - Deprecated
AsyncValue.data
in favor ofAsyncValue.value
- Allowed
AsyncData
,AsyncError
andAsyncLoading
to be extended - Added
AsyncValue.whenOrNull
, similar towhenOrElse
but instead of an "orElse" parameter, returnsnull
. - Added
AsyncValue.value
, which allows reading the value without handling loading/error states. AsyncError
can now be instantiated withconst
.AsyncLoading
andAsyncError
now optionally includes the previous state.
-
Breaking All
overrideWithProvider
methods are removed. To migrate, instead useoverrideWithValue
. -
All providers now come with an extra named parameter called
dependencies
. This parameter optionally allows defining the list of providers/families that this new provider depends on:final a = Provider(...); final b = Provider((ref) => ref.watch(a), dependencies: [a]);
By doing so, this will tell Riverpod to automatically override
b
ifa
gets overridden. -
Added
StatefulHookConsumerWidget
, the combination ofStatefulWidget
+ConsumerWidget
+HookWidget
-
Added
StateController.update
, to simplify updating the state from the previous state:final provider = StateController((ref) => 0); ... ref.read(provider).update((state) => state + 1);
-
It is no longer allowed to use
ref.watch
orref.read
inside a selector:provider.select((value) => ref.watch(something)); // KO, cannot user ref.watch inside selectors
- fixed a bug where providers were rebuilding even when not listened to
- fixed
ref.listen
now working when downcasting the value of a provider. - fixed a bug where disposing a scoped
ProviderContainer
could cause otherProviderContainer
s to stop working. - fixed an issue where conditionally depending on an "autoDispose" provider may not properly dispose of it (see #712)
- fixed an issue where when chaining providers, widgets may re-render a frame late, potentially causing a flicker. (see #648)
- Fixed
ProviderObserver
not working when modifying aStateProvider
. - Fixed a bug where scoped provider were potentially not disposed
- Fixed a bug where widgets were not rebuilding in release mode under certain conditions
- FIX: StreamProvider.last no longer throws a StateError when no value were emitted (#296).
- Re-enabled debug assertions that were temporarily disabled by previous dev versions.
- Allows families to be scoped/overridden
- Fixed bugs with
ref.refresh
not working on some providers - renamed
ProviderBase.recreateShouldNotify
toupdateShouldNotify
Fixed an issue where provider listeners could not be called properly.
Fixed invalid flutter_hooks version
Fixed various issues related to scoped providers.
- All providers can now be scoped.
- breaking:
ScopedProvider
is removed. To migrate, changeScopedProvider
s toProvider
s.
- Add missing exports (see #532)
-
useProvider
is removed in favor ofHookConsumerWidget
. Before:class Example extends HookWidget { @override Widget build(BuildContext context) { useState(...); int count = useProvider(counterProvider); ... } }
After:
class Example extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { useState(...); int count = ref.watch(counterProvider); ... } }
-
Breaking: The prototype of
ConsumerWidget
'sbuild
andConsumer
'sbuilder
changed. Before:class Example extends ConsumerWidget { @override Widget build(BuildContext context, ScopedReader watch) { int count = watch(counterProvider); ... } }
After:
class Example extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { int count = ref.watch(counterProvider); ... } }
-
ProviderListener
is deprecated. Instead, useref.listen
:class Example extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { ref.listen<int>(counter, (count) { print('count changed $count'); }); } }
-
Added
ConsumerStatefulWidget
+ConsumerState
, a variant ofStatefulWidget
s that have access to aWidgetRef
. -
All "watch" functions now support
myProvider.select((value) => ...)
. This allows filtering rebuilds:final userProvider = StateNotifierProvider<UserController, User>(...); Consumer( builder: (context, ref, _) { // With this syntax, the Consumer will not rebuild if `userProvider` // emits a new User but its "name" didn't change. bool userName = ref.watch(userProvider.select((user) => user.name)); }, )
-
Breaking:
Family.overrideWithProvider
now must create a provider:final family = Provider.family<State, Arg>(...); family.overrideWithProvider( (Arg arg) => Provider<State>((ref) => ...) );
-
Breaking:
ProviderObserver.didUpdateProvider
now receives both the previous and new value. -
Breaking:
ProviderObserver.mayHaveChanged
is removed. -
Added
ref.listen
, used to listen to another provider without recreating the provider state:final counter = StateNotifierProvider<Counter, int>(...); final anotherProvider = Provider<T>((ref) { ref.listen<int>(counter, (count) { print('counter change: $count'); }); });
-
ProviderReference
is deprecated in favor ofProviderRefBase
. -
All providers now receive a custom subclass of
ProviderRefBase
as a parameter:Provider<T>((ProviderRef<T> ref) {...}); FutureProvider<T>((FutureProviderRef<T> ref) {...}); StateProvider<T>((StateProviderRef<T> ref) {...});
That allows providers to implement features that is not shared with other providers.
-
Provider
,FutureProvider
andStreamProvider
'sref
now have astate
property, which represents the currently exposed value. Modifying it will notify the listeners:Provider<int>((ref) { ref.listen(onIncrementProvider, (_) { ref.state++; }); return 0; });
-
StateProvider
'sref
now has acontroller
property, which allows the provider to access theStateController
exposed.
-
-
Breaking:
ProviderReference.mounted
is removed. You can implement something similar usingonDispose
:Provider<T>((ref) { var mounted = true; ref.onDispose(() => mounted = false); });
-
Breaking:
ProviderContainer.debugProviderValues
andProviderContainer.debugProviderElements
are removed. You can now instead useProviderContainer.getAllProviderElements
. -
StreamProvider.last
,StreamProvider.stream
andFutureProvider.future
now expose a future/stream that is independent from how many times the associated provider "rebuilt":- if a
StreamProvider
rebuild before its stream emitted any value,StreamProvider.last
will resolve with the first value of the new stream instead. - if a
FutureProvider
rebuild before its future completes,FutureProvider.future
will resolve with the result of the new future instead.
- if a
-
You can now override any provider with any other provider, as long as the value that they expose matches. For example, it is possible to override a
StreamProvider<Model>
with aProvider<AsyncValue<Model>>
. -
Providers can now call
ref.refresh
to refresh a provider, instead of having to doref.container.refresh
. -
ref.onDispose
now calls the dispose function as soon as one of the provider's dependency is known to have changed -
Providers no longer wait until their next read to recompute their state if one of their dependency changed and they have listeners.
-
Added
ProviderContainer.pump
, a utility to easily "await" until providers notify their listeners or are disposed. -
fixed an issue when using both
family
andautoDispose
that could lead to an inconsistent state
Upgraded dependencies to latest
Removed an assert that could cause issues when an application is partially migrated to null safety.
- Fix
context.refresh
not compiling when using nullable providers
- Re-added
StateProvider.overrideWithValue
/StateProvider.overrideWithProvider
that were unvoluntarily removed.
-
BREAKING CHANGE The
Listener
/LocatorMixin
typedefs are removed as the former could cause a name conflict with the widget namedListener
and the latter is not supported when using Riverpod. -
BREAKING CHANGE The syntax for using
StateNotifierProvider
was updated. Before:class MyStateNotifier extends StateNotifier<MyModel> {...} final provider = StateNotifierProvider<MyStateNotifier>((ref) => MyStateNotifier()); ... Widget build(context, watch) { MyStateNotifier notifier = watch(provider); MyModel model = watch(provider.state); }
After:
class MyStateNotifier extends StateNotifier<MyModel> {...} final provider = StateNotifierProvider<MyStateNotifier, MyModel>>((ref) => MyStateNotifier()); ... Widget build(context, watch) { MyStateNotifier notifier = watch(provider.notifier); MyModel model = watch(provider); }
See also #341 for more information.
-
BREAKING CHANGE It is no longer possible to override
StreamProvider.stream/last
andFutureProvider.future
. -
feat: Calling
ProviderContainer.dispose
multiple time no longer throws. This simplifies the tear-off logic of tests. -
feat: Added
ChangeNotifierProvider.notifier
andStateProvider.notifier
They allow obtaining the notifier associated with the provider, without causing widgets/providers to rebuild when the state updates. -
fix: overriding a
StateNotifierProvider
/ChangeNotifierProvider
withoverrideWithValue
now correctly listens to the notifier.
Fixed an issue where context.read
and ProviderListener
were unable to read providers that return a nullable value
- Fixed a bug where overriding a
FutureProvider
with an error value could cause tests to fail (see #355)
- stable null-safety release
ProviderObserver
can now have a const constructor- Added the mechanism for state-inspection using the Flutter devtool
- loosened the version constraints of
freezed_annotation
- deprecated
import 'hooks_riverpod/all.dart'
. Now everything is available withhooks_riverpod/hooks_riverpod.dart
. - Fixed a but where listening to
StreamProvider.last
could result in aStateError
(#217) - removed the assert preventing ConsumerWidget's "watch" from being used after the
build
method completed. This allows "watch" to be used insideListView.builder
. context.read(myProvider)
now acceptsScopeProviders
- deprecated
import 'hooks_riverpod/all.dart'
. Now everything is available withhooks_riverpod/hooks_riverpod.dart
. - removed the assert preventing ConsumerWidget's "watch" from being used after the
build
method completed. This allows "watch" to be used insideListView.builder
. context.read(myProvider)
now acceptsScopeProviders
- Fixed outdated doc
- Fixed a but where listening to
StreamProvider.last
could result in aStateError
(#217)
Migrated to null-safety
- Exported
AutoDisposeProviderRefBase
- Fixed an remaining memory leak related to StreamProvider (see also #193)
- Breaking FutureProvider and StreamProvider no longer supports
null
as a valid value. - Fixed a memory leak with StreamProvider (see also #193)
- Fixed an error message typo related to Consumer
- Fixed a bug where providers (usually ScopedProviders) did not dispose correctly (see also #154).
- Fixed a bug where hot-reload did not work for
ConsumerWidget
/Consumer
package:hooks_riverpod/hooks_riverpod.dart
now exportsStateNotifier
- Marked the providers with
@sealed
so that the IDE warns against implementing/subclassing providers. - Fix mistakes in
AsyncValue.guard
's documentation (thanks @mono0926) - Loosened the version constraints of
freezed_annotation
to support0.12.0
- Fixed invalid version error
-
Fixed a bug where the state of a provider may be disposed when it shouldn't be disposed.
-
Added a way to import the implementation class of providers with modifiers, such as
AutoDisposeProvider
.This is useful if you want to use Riverpod with the lint
always_specify_types
:import 'package:hooks_riverpod/all.dart'; final AutoDisposeStateProvider<int> counter = StateProvider.autoDispose<int>((ProviderRefBase ref) { return 0; });
If you do not use this lint, prefer using the default import instead, to not pollute your auto-complete.
- Unexported some classes that were not meant to be public
- Breaking Updating
ProviderListener
so thatonChange
receives theBuildContext
as a parameter (thanks to @tbm98)
- Renamed
ProviderContainer.debugProviderStates
toProviderContainer.debugProviderElements
- Fixed a bug where updating
ProviderScope.overrides
may cause an exception for no reason (see #107)
Fixed a bug that prevented the use of ConsumerWidget
under normal circumstances
- Fixed a bug where in release mode,
ScopedProvider
did not update correctly (#101)
-
Breaking:
Consumer
is slightly modified to match other Builders likeValueListenableBuilder
. Before:return Consumer((context, watch) { final value = watch(myProvider); return Text('$value'); });
after:
return Consumer( builder: (context, watch, child) { final value = watch(myProvider); return Text('$value'); }, );
-
Added a
ConsumerWidget
class which can be extended to make aStatelessWidget
that can read providers:class MyWidget extends ConsumerWidget { const MyWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final value = watch(myProvider); return Text('$value'); } }
-
ref.watch
on non ".autoDispose" providers can no longer read ".autoDispose" providers.For more info, see http://riverpod.dev/docs/concepts/modifiers/auto_dispose#the-argument-type-autodisposeprovider-cant-be-assigned-to-the-parameter-type-alwaysaliveproviderbase
-
ScopedProvider
now acceptsnull
as a function:final example = ScopedProvider<int>(null);
Which is equivalent to:
final example = ScopedProvider<int>((watch) => throw UnimplementedError(''));
- Fixed a bug where
context.refresh
may not work properly if the widget tree contains multipleProviderScope
.
- Fixed a bug where when disposing
ProviderContainer
, providers may be disposed in an incorrect order. - Improved the performances of reading providers by 25%
-
Merged
Computed
andProvider
. Now, all providers have the ability to rebuild their state when one of the object they listen changed.To migrate, change:
final provider = Provider(...); final example = Computed((watch) { final value = watch(provider); return value; });
into:
final provider = Provider(...); final example = Provider((ref) { final value = ref.watch(provider); return value; });
-
Computed
(nowProvider
) no longer deeply compare collections to avoid rebuilds. Comparing the content of lists is quite expensive and actually rarely useful. Now, a simple==
comparison is used. -
Renamed
ProviderStateOwner
toProviderContainer
-
Renamed
ProviderStateOwnerObserver
toProviderObserver
-
It is no longer possible to override a provider anywhere in the widget tree. Providers can only be overridden in the top-most
ProviderScope
/ProviderContainer
. -
Providers can now read values which may change over time using
ref.read
andref.watch
. When usingref.watch
, if the value obtained changes, this will cause the provider to re-create its state. -
It is no longer possible to add
ProviderObserver
anywhere in the widget tree. They can be added only on the top-mostProviderScope
/ProviderContainer
. -
Provider.read(BuildContext)
is changed intocontext.read(provider)
, and can now readProvider.autoDispose
. -
Added
ProviderContainer.refresh(provider)
andcontext.refresh(provider)
. These method allows forcing the refresh of a provider, which can be useful for things like "retry on error" or "pull to refresh".
-
ref.read(StreamProvider<T>)
no longer returns aStream<T>
but anAsyncValue<T>
Before:final streamProvider = StreamProvider<T>(...); final example = Provider((ref) { Stream<T> stream = ref.read(streamProvider); });
After:
final streamProvider = StreamProvider<T>(...); final example = Provider((ref) { Stream<T> stream = ref.watch(streamProvider.steam); });
-
ref.read(FutureProvider<T>)
no longer returns aFuture<T>
but anAsyncValue<T>
Before:
final futureProvider = FutureProvider<T>(...); final example = Provider((ref) { Future<T> future = ref.read(futureProvider); });
After:
final futureProvider = FutureProvider<T>(...); final example = Provider((ref) { Future<T> future = ref.watch(futureProvider.future); });
-
Removed
ref.dependOn
. You can now useref.read
/ref.watch
to achieve the same effect.Before:
final streamProvider = StreamProvider<T>(...); final example = Provider((ref) { Future<T> last = ref.dependOn(streamProvider).last; });
After:
final streamProvider = StreamProvider<T>(...); final example = Provider((ref) { Future<T> last = ref.watch(streamProvider.last); });
-
Provider.readOwner(ProviderStateOwner)
is changed intoProviderContainer.read(Provider)
-
Provider.watchOwner(ProviderStateOwner, (value) {})
is changed into:ProviderContainer container; final provider = Provider((ref) => 0); final subscription = container.listen( provider, mayHaveChanged: (sub) {}, didChange: (sub) {}. ); subscription.close();
-
MyProvider.family.autoDispose
now correctly free both the arguments and the associated providers from memory when the provider is no longer listened to.
-
Added
ScopedProvider
, a new kind of provider that can be overridden anywhere in the widget tree. Normal providers cannot read aScopedProvider
. -
Added
ProviderListener
, a widget which allows listening to a provider without rebuilding the widget-tree. This can be useful for showing modals and pushing routes.
- Fixed the documentation of
StateNotifierProvider
incorrectly showing the documentation ofStreamProvider
. - Improve the documentation of
StateProvider
.
- Changed
ComputedFamily
intoComputed.family
- Added [AsyncValue.guard](https://pub.dev/documentation/riverpod/latest/riverpod/AsyncValue/guard.html to simplify transforming a Future into an AsyncValue.
- Improved the documentation of the different providers
Changed the syntax of "AutoDispose*" and "*Family" to use a syntax similar to named constructors instead.
Before:
final myProvider = AutoDisposeStateNotifierProviderFamily<MyStateNotifier, int>((ref, id) {
return MyStateNotifier(id: id);
});
After:
final myProvider = StateNotifierProvider.autoDispose.family<MyStateNotifier, int>((ref, id) {
return MyStateNotifier(id: id);
});
The behavior is the same. Only the syntax changed.
- Loosen the version constraint of
flutter_hooks
used to support latest versions.
-
Added
AsyncValue.whenData
, syntax sugar forAsyncValue.when
to handle only thedata
case and do nothing for the error/loading cases. -
Fixed a bug that caused [Computed] to crash if it stopped being listened to then was listened to again.
-
useProvider
no longer throws anUnsupportedError
when the provider being listened to changes, and correctly listens to the new provider. -
Computed
andConsumer
now correctly unsubscribe to a provider when their function stops using a provider.
ref.read
is renamed asref.dependOn
- Deprecated
ref.dependOn(streamProvider).stream
andref.dependOn(futureProvider).future
in favor of a universalref.dependOn(provider).value
. - added
ref.read(provider)
, syntax sugar forref.dependOn(provider).value
.
Initial release