Repository: rrousselGit/riverpod

Issue:
2.0-dev "listenSelf" on StateNotifier should track the state not notifier
2.0.0-dev.4 introduces `listenSelf` on providers. When used with a `StateNotifierProvider` the arguments to the `listenSelf` function are typed for the notifier and not the state. We were expecting that the `listenSelf` would track state changes - especially since a likely pattern already provides access to the notifier.

```dart
final aProvider = StateNotifierProvider<ANotifier, AState>((ref) {
  final aNotifier = ANotifier();
  ref.listenSelf((ANotifier? previous, ANotifier notAState) {});  // <-- expecting this to track state, have the notifier in scope
  return aNotifier;
});
```

ref.refresh(autoDispose.future) should not throw "Future disposed before a value was emitted"




Fix patch:
diff --git a/packages/flutter_riverpod/CHANGELOG.md b/packages/flutter_riverpod/CHANGELOG.md
index 934115b623..131cbc67bd 100644
--- a/packages/flutter_riverpod/CHANGELOG.md
+++ b/packages/flutter_riverpod/CHANGELOG.md
@@ -1,3 +1,9 @@
+# Unrelased major
+
+**Breaking changes**:
+
+- Removed the deprecated `ProviderListener` and `OnProviderChange`.
+
 # 2.0.0-dev.9
 
 Fix Timer leak when using `cacheTime`/`disposeDelay` and disposing a `ProviderContainer`
diff --git a/packages/flutter_riverpod/lib/flutter_riverpod.dart b/packages/flutter_riverpod/lib/flutter_riverpod.dart
index fa4cb7ba93..26b4c18d27 100644
--- a/packages/flutter_riverpod/lib/flutter_riverpod.dart
+++ b/packages/flutter_riverpod/lib/flutter_riverpod.dart
@@ -20,5 +20,3 @@ export 'src/consumer.dart'
         ConsumerStatefulElement;
 
 export 'src/framework.dart' show ProviderScope, UncontrolledProviderScope;
-// ignore: deprecated_member_use_from_same_package
-export 'src/provider_listener.dart' show ProviderListener, OnProviderChange;
diff --git a/packages/flutter_riverpod/lib/src/change_notifier_provider.dart b/packages/flutter_riverpod/lib/src/change_notifier_provider.dart
index 06ae0a30c6..3b29243a68 100644
--- a/packages/flutter_riverpod/lib/src/change_notifier_provider.dart
+++ b/packages/flutter_riverpod/lib/src/change_notifier_provider.dart
@@ -1,5 +1,4 @@
 import 'package:flutter/widgets.dart';
-import 'package:meta/meta.dart';
 // ignore: implementation_imports
 import 'package:riverpod/src/internals.dart';
 
@@ -8,48 +7,59 @@ import 'builders.dart';
 part 'change_notifier_provider/auto_dispose.dart';
 part 'change_notifier_provider/base.dart';
 
+ProviderElementProxy<NotifierT, NotifierT>
+    _notifier<NotifierT extends ChangeNotifier?>(
+  _ChangeNotifierProviderBase<NotifierT> that,
+) {
+  return ProviderElementProxy<NotifierT, NotifierT>(
+    that,
+    (element) {
+      return (element as ChangeNotifierProviderElement<NotifierT>)
+          ._notifierNotifier;
+    },
+  );
+}
+
+// ignore: subtype_of_sealed_class
 /// {@template riverpod.changenotifierprovider}
 /// Creates a [ChangeNotifier] and subscribes to it.
 ///
 /// Note: By using Riverpod, [ChangeNotifier] will no longer be O(N^2) for
 /// dispatching notifications, but instead O(N)
 /// {@endtemplate}
-T _listenNotifier<T extends ChangeNotifier?>(
-  T notifier,
-  ProviderElementBase<T> ref,
-) {
-  if (notifier != null) {
-    void listener() {
-      ref.setState(notifier);
-    }
-
-    notifier.addListener(listener);
-    ref.onDispose(() {
-      try {
-        notifier.removeListener(listener);
-        // ignore: empty_catches, may throw if called after the notifier is dispose, but this is safe to ignore.
-      } catch (err) {}
-    });
-  }
-
-  return notifier;
-}
+abstract class _ChangeNotifierProviderBase<NotifierT extends ChangeNotifier?>
+    extends ProviderBase<NotifierT> {
+  _ChangeNotifierProviderBase({
+    required super.name,
+    required super.from,
+    required super.argument,
+    required this.dependencies,
+    required super.cacheTime,
+    required super.disposeDelay,
+  });
 
-// ignore: subtype_of_sealed_class
-/// Add [overrideWithValue] to [AutoDisposeStateNotifierProvider]
-mixin ChangeNotifierProviderOverrideMixin<Notifier extends ChangeNotifier?>
-    on ProviderBase<Notifier> {
+  @override
+  final List<ProviderOrFamily>? dependencies;
+
+  /// Obtains the [ChangeNotifier] associated with this provider, without listening
+  /// to state changes.
   ///
-  ProviderBase<Notifier> get notifier;
+  /// This is typically used to invoke methods on a [ChangeNotifier]. For example:
+  ///
+  /// ```dart
+  /// Button(
+  ///   onTap: () => ref.read(changeNotifierProvider.notifer).increment(),
+  /// )
+  /// ```
+  ///
+  /// This listenable will notify its notifiers if the [ChangeNotifier] instance
+  /// changes.
+  /// This may happen if the provider is refreshed or one of its dependencies
+  /// has changes.
+  ProviderListenable<NotifierT> get notifier;
+
+  NotifierT _create(covariant ChangeNotifierProviderElement<NotifierT> ref);
 
   @override
-  late final List<ProviderOrFamily>? dependencies = [notifier];
-
-  /// {@macro riverpod.overrridewithvalue}
-  Override overrideWithValue(Notifier value) {
-    return ProviderOverride(
-      origin: notifier,
-      override: ValueProvider<Notifier>(value),
-    );
-  }
+  bool updateShouldNotify(NotifierT previousState, NotifierT newState) => true;
 }
diff --git a/packages/flutter_riverpod/lib/src/change_notifier_provider/auto_dispose.dart b/packages/flutter_riverpod/lib/src/change_notifier_provider/auto_dispose.dart
index 820b2cbc63..2dc3b67070 100644
--- a/packages/flutter_riverpod/lib/src/change_notifier_provider/auto_dispose.dart
+++ b/packages/flutter_riverpod/lib/src/change_notifier_provider/auto_dispose.dart
@@ -1,181 +1,68 @@
 part of '../change_notifier_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
-abstract class AutoDisposeChangeNotifierProviderRef<Notifier>
-    implements AutoDisposeRef<Notifier> {
-  /// The [ChangeNotifier] currently exposed by this provider.
-  ///
-  /// Cannot be accessed while creating the provider.
-  Notifier get notifier;
-}
+abstract class AutoDisposeChangeNotifierProviderRef<
+        NotifierT extends ChangeNotifier?>
+    extends ChangeNotifierProviderRef<NotifierT>
+    implements AutoDisposeRef<NotifierT> {}
 
 // ignore: subtype_of_sealed_class
-/// {@macro riverpod.changenotifierprovider}
-@sealed
-class AutoDisposeChangeNotifierProvider<Notifier extends ChangeNotifier?>
-    extends AutoDisposeProviderBase<Notifier>
-    with
-        ChangeNotifierProviderOverrideMixin<Notifier>,
-        OverrideWithProviderMixin<Notifier,
-            AutoDisposeChangeNotifierProvider<Notifier>> {
-  /// {@macro riverpod.changenotifierprovider}
+/// {@macro riverpod.ChangeNotifierprovider}
+class AutoDisposeChangeNotifierProvider<NotifierT extends ChangeNotifier?>
+    extends _ChangeNotifierProviderBase<NotifierT> {
+  /// {@macro riverpod.ChangeNotifierprovider}
   AutoDisposeChangeNotifierProvider(
-    Create<Notifier, AutoDisposeChangeNotifierProviderRef<Notifier>> create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Family? from,
-    Object? argument,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  })  : notifier = _AutoDisposeNotifierProvider<Notifier>(
-          create,
-          name: modifierName(name, 'notifier'),
-          dependencies: dependencies,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-        ),
-        super(
-          name: name,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  });
 
   /// {@macro riverpod.family}
-  static const family = AutoDisposeChangeNotifierProviderFamilyBuilder();
-
-  @override
-  ProviderBase<Notifier> get originProvider => notifier;
-
-  /// {@macro flutter_riverpod.changenotifierprovider.notifier}
-  @override
-  final AutoDisposeProviderBase<Notifier> notifier;
-
-  @override
-  Notifier create(AutoDisposeProviderElementBase<Notifier> ref) {
-    final notifier = ref.watch<Notifier>(this.notifier);
-    _listenNotifier(notifier, ref);
-    return notifier;
-  }
-
-  @override
-  bool updateShouldNotify(Notifier previousState, Notifier newState) => true;
-
-  @override
-  AutoDisposeProviderElement<Notifier> createElement() =>
-      AutoDisposeProviderElement(this);
-}
-
-// ignore: subtype_of_sealed_class
-class _AutoDisposeNotifierProvider<Notifier extends ChangeNotifier?>
-    extends AutoDisposeProviderBase<Notifier> {
-  _AutoDisposeNotifierProvider(
-    this._create, {
-    required String? name,
-    required this.dependencies,
-    Family? from,
-    Object? argument,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: modifierName(name, 'notifier'),
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  @override
-  final List<ProviderOrFamily>? dependencies;
+  static const family = AutoDisposeChangeNotifierProviderFamily.new;
 
-  final Create<Notifier, AutoDisposeChangeNotifierProviderRef<Notifier>>
-      _create;
+  final NotifierT Function(AutoDisposeChangeNotifierProviderRef<NotifierT> ref)
+      _createFn;
 
   @override
-  Notifier create(
-    covariant AutoDisposeChangeNotifierProviderRef<Notifier> ref,
-  ) {
-    final notifier = _create(ref);
-    if (notifier != null) ref.onDispose(notifier.dispose);
-
-    return notifier;
+  NotifierT _create(AutoDisposeChangeNotifierProviderElement<NotifierT> ref) {
+    return _createFn(ref);
   }
 
   @override
-  _AutoDisposeNotifierProviderElement<Notifier> createElement() {
-    return _AutoDisposeNotifierProviderElement<Notifier>(this);
+  AutoDisposeChangeNotifierProviderElement<NotifierT> createElement() {
+    return AutoDisposeChangeNotifierProviderElement<NotifierT>._(this);
   }
 
   @override
-  bool updateShouldNotify(Notifier previousState, Notifier newState) => true;
+  late final Refreshable<NotifierT> notifier = _notifier<NotifierT>(this);
 }
 
-class _AutoDisposeNotifierProviderElement<Notifier extends ChangeNotifier?>
-    extends AutoDisposeProviderElementBase<Notifier>
-    implements AutoDisposeChangeNotifierProviderRef<Notifier> {
-  _AutoDisposeNotifierProviderElement(
-      _AutoDisposeNotifierProvider<Notifier> provider)
-      : super(provider);
-
-  @override
-  Notifier get notifier => requireState;
-}
+/// The element of [AutoDisposeChangeNotifierProvider].
+class AutoDisposeChangeNotifierProviderElement<
+        NotifierT extends ChangeNotifier?> = ChangeNotifierProviderElement<NotifierT>
+    with AutoDisposeProviderElementMixin<NotifierT>
+    implements AutoDisposeChangeNotifierProviderRef<NotifierT>;
 
 // ignore: subtype_of_sealed_class
-/// {@macro riverpod.changenotifierprovider.family}
-@sealed
-class AutoDisposeChangeNotifierProviderFamily<Notifier extends ChangeNotifier?,
+/// The [Family] of [AutoDisposeChangeNotifierProvider].
+class AutoDisposeChangeNotifierProviderFamily<NotifierT extends ChangeNotifier?,
         Arg>
-    extends Family<Notifier, Arg, AutoDisposeChangeNotifierProvider<Notifier>> {
-  /// {@macro riverpod.changenotifierprovider.family}
+    extends AutoDisposeFamilyBase<
+        AutoDisposeChangeNotifierProviderRef<NotifierT>,
+        NotifierT,
+        Arg,
+        NotifierT,
+        AutoDisposeChangeNotifierProvider<NotifierT>> {
+  /// The [Family] of [AutoDisposeChangeNotifierProvider].
   AutoDisposeChangeNotifierProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          dependencies: dependencies,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final FamilyCreate<Notifier, AutoDisposeChangeNotifierProviderRef<Notifier>,
-      Arg> _create;
-
-  @override
-  AutoDisposeChangeNotifierProvider<Notifier> create(Arg argument) {
-    return AutoDisposeChangeNotifierProvider<Notifier>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-    );
-  }
-
-  @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final provider = call(argument);
-
-    setup(origin: provider, override: provider);
-    setup(origin: provider.notifier, override: provider.notifier);
-  }
-
-  /// {@endtemplate}
-  Override overrideWithProvider(
-    AutoDisposeChangeNotifierProvider<Notifier> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(
-      this,
-      (arg, setup) {
-        final provider = call(arg);
-
-        setup(origin: provider.notifier, override: override(arg).notifier);
-        setup(origin: provider, override: provider);
-      },
-    );
-  }
+    super.create, {
+    super.name,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  }) : super(providerFactory: AutoDisposeChangeNotifierProvider.new);
 }
diff --git a/packages/flutter_riverpod/lib/src/change_notifier_provider/base.dart b/packages/flutter_riverpod/lib/src/change_notifier_provider/base.dart
index 5bce634e67..8b7a6b3a18 100644
--- a/packages/flutter_riverpod/lib/src/change_notifier_provider/base.dart
+++ b/packages/flutter_riverpod/lib/src/change_notifier_provider/base.dart
@@ -1,216 +1,184 @@
 part of '../change_notifier_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
-abstract class ChangeNotifierProviderRef<Notifier extends ChangeNotifier?>
-    implements Ref<Notifier> {
+abstract class ChangeNotifierProviderRef<NotifierT extends ChangeNotifier?>
+    implements Ref<NotifierT> {
   /// The [ChangeNotifier] currently exposed by this provider.
   ///
   /// Cannot be accessed while creating the provider.
-  Notifier get notifier;
+  NotifierT get notifier;
 }
 
 // ignore: subtype_of_sealed_class
-/// {@macro riverpod.changenotifierprovider}
-@sealed
-class ChangeNotifierProvider<Notifier extends ChangeNotifier?>
-    extends AlwaysAliveProviderBase<Notifier>
-    with
-        ChangeNotifierProviderOverrideMixin<Notifier>,
-        OverrideWithProviderMixin<Notifier, ChangeNotifierProvider<Notifier>> {
-  /// {@macro riverpod.changenotifierprovider}
+/// {@template riverpod.ChangeNotifierprovider}
+/// Creates a [ChangeNotifier] and exposes its current state.
+///
+/// This provider is used in combination with `package:state_notifier`.
+///
+/// Combined with [ChangeNotifier], [ChangeNotifierProvider] can be used to manipulate
+/// advanced states, that would otherwise be difficult to represent with simpler
+/// providers such as [Provider] or [FutureProvider].
+///
+/// For example, you may have a todo-list, where you can add and remove
+/// and complete a todo.
+/// Using [ChangeNotifier], you could represent such state as:
+///
+/// ```dart
+/// class TodosNotifier extends ChangeNotifier<List<Todo>> {
+///   TodosNotifier(): super([]);
+///
+///   void add(Todo todo) {
+///     state = [...state, todo];
+///   }
+///
+///   void remove(String todoId) {
+///     state = [
+///       for (final todo in state)
+///         if (todo.id != todoId) todo,
+///     ];
+///   }
+///
+///   void toggle(String todoId) {
+///     state = [
+///       for (final todo in state)
+///         if (todo.id == todoId) todo.copyWith(completed: !todo.completed),
+///     ];
+///   }
+/// }
+/// ```
+///
+/// Which you can then pass to a [ChangeNotifierProvider] like so:
+///
+/// ```dart
+/// final todosProvider = ChangeNotifierProvider<TodosNotifier, List<Todo>>((ref) => TodosNotifier());
+/// ```
+///
+/// And finally, you can interact with it inside your UI:
+///
+/// ```dart
+/// Widget build(BuildContext context, WidgetRef ref) {
+///   // rebuild the widget when the todo list changes
+///   List<Todo> todos = ref.watch(todosProvider);
+///
+///   return ListView(
+///     children: [
+///       for (final todo in todos)
+///         CheckboxListTile(
+///            value: todo.completed,
+///            // When tapping on the todo, change its completed status
+///            onChanged: (value) => ref.read(todosProvider.notifier).toggle(todo.id),
+///            title: Text(todo.description),
+///         ),
+///     ],
+///   );
+/// }
+/// ```
+/// {@endtemplate}
+class ChangeNotifierProvider<NotifierT extends ChangeNotifier?>
+    extends _ChangeNotifierProviderBase<NotifierT>
+    with AlwaysAliveProviderBase<NotifierT> {
+  /// {@macro riverpod.ChangeNotifierprovider}
   ChangeNotifierProvider(
-    Create<Notifier, ChangeNotifierProviderRef<Notifier>> create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Family? from,
-    Object? argument,
-  })  : notifier = _NotifierProvider<Notifier>(
-          create,
-          name: name,
-          dependencies: dependencies,
-          from: from,
-          argument: argument,
-        ),
-        super(name: name, from: from, argument: argument);
-
-  /// {@macro riverpod.family}
-  static const family = ChangeNotifierProviderFamilyBuilder();
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+  }) : super(cacheTime: null, disposeDelay: null);
 
   /// {@macro riverpod.autoDispose}
   static const autoDispose = AutoDisposeChangeNotifierProviderBuilder();
 
-  @override
-  ProviderBase<Notifier> get originProvider => notifier;
+  /// {@macro riverpod.family}
+  static const family = ChangeNotifierProviderFamilyBuilder();
 
-  /// {@template flutter_riverpod.changenotifierprovider.notifier}
-  /// Obtains the [ChangeNotifier] associated with this provider, but without
-  /// listening to it.
-  ///
-  /// Listening to this provider may cause providers/widgets to rebuild in the
-  /// event that the [ChangeNotifier] it recreated.
-  ///
-  ///
-  /// It is preferable to do:
-  /// ```dart
-  /// ref.watch(changeNotifierProvider.notifier)
-  /// ```
-  ///
-  /// instead of:
-  /// ```dart
-  /// ref.read(changeNotifierProvider)
-  /// ```
-  ///
-  /// The reasoning is, using `read` could cause hard to catch bugs, such as
-  /// not rebuilding dependent providers/widgets after using `ref.refresh` on this provider.
-  /// {@endtemplate}
-  @override
-  final AlwaysAliveProviderBase<Notifier> notifier;
+  final NotifierT Function(ChangeNotifierProviderRef<NotifierT> ref) _createFn;
 
   @override
-  Notifier create(ProviderElementBase<Notifier> ref) {
-    final notifier = ref.watch<Notifier>(this.notifier);
-    _listenNotifier(notifier, ref);
-    return notifier;
+  NotifierT _create(ChangeNotifierProviderElement<NotifierT> ref) {
+    return _createFn(ref);
   }
 
   @override
-  ProviderElement<Notifier> createElement() {
-    return ProviderElement(this);
+  ChangeNotifierProviderElement<NotifierT> createElement() {
+    return ChangeNotifierProviderElement<NotifierT>._(this);
   }
 
   @override
-  bool updateShouldNotify(Notifier previousState, Notifier newState) => true;
+  late final AlwaysAliveRefreshable<NotifierT> notifier =
+      _notifier<NotifierT>(this);
 }
 
-// ignore: subtype_of_sealed_class
-class _NotifierProvider<Notifier extends ChangeNotifier?>
-    extends AlwaysAliveProviderBase<Notifier> {
-  _NotifierProvider(
-    this._create, {
-    required String? name,
-    required this.dependencies,
-    Family? from,
-    Object? argument,
-  }) : super(
-          name: modifierName(name, 'notifier'),
-          from: from,
-          argument: argument,
-        );
-
-  @override
-  final List<ProviderOrFamily>? dependencies;
-
-  final Create<Notifier, ChangeNotifierProviderRef<Notifier>> _create;
+/// The element of [ChangeNotifierProvider].
+class ChangeNotifierProviderElement<NotifierT extends ChangeNotifier?>
+    extends ProviderElementBase<NotifierT>
+    implements ChangeNotifierProviderRef<NotifierT> {
+  ChangeNotifierProviderElement._(
+    _ChangeNotifierProviderBase<NotifierT> provider,
+  ) : super(provider);
 
   @override
-  Notifier create(covariant ChangeNotifierProviderRef<Notifier> ref) {
-    final notifier = _create(ref);
-    if (notifier != null) ref.onDispose(notifier.dispose);
-
-    return notifier;
-  }
+  NotifierT get notifier => _notifierNotifier.value;
+  final _notifierNotifier = ProxyElementValueNotifier<NotifierT>();
 
-  @override
-  _NotifierProviderElement<Notifier> createElement() {
-    return _NotifierProviderElement<Notifier>(this);
-  }
+  void Function()? _removeListener;
 
   @override
-  bool updateShouldNotify(Notifier previousState, Notifier newState) => true;
-}
+  void create() {
+    final provider = this.provider as _ChangeNotifierProviderBase<NotifierT>;
 
-class _NotifierProviderElement<Notifier extends ChangeNotifier?>
-    extends ProviderElementBase<Notifier>
-    implements ChangeNotifierProviderRef<Notifier> {
-  _NotifierProviderElement(_NotifierProvider<Notifier> provider)
-      : super(provider);
+    final notifierResult =
+        _notifierNotifier.result = Result.guard(() => provider._create(this));
 
-  @override
-  Notifier get notifier => requireState;
-}
+    // TODO test requireState, as ref.read(p) is expected to throw if notifier creation failed
+    final notifier = notifierResult.requireState;
 
-// ignore: subtype_of_sealed_class
-/// {@template riverpod.changenotifierprovider.family}
-/// A class that allows building a [ChangeNotifierProvider] from an external parameter.
-/// {@endtemplate}
-@sealed
-class ChangeNotifierProviderFamily<Notifier extends ChangeNotifier?, Arg>
-    extends Family<Notifier, Arg, ChangeNotifierProvider<Notifier>> {
-  /// {@macro riverpod.changenotifierprovider.family}
-  ChangeNotifierProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-  }) : super(name: name, dependencies: dependencies);
+    setState(notifier);
 
-  final FamilyCreate<Notifier, ChangeNotifierProviderRef<Notifier>, Arg>
-      _create;
-
-  @override
-  ChangeNotifierProvider<Notifier> create(Arg argument) {
-    return ChangeNotifierProvider<Notifier>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-    );
+    if (notifier != null) {
+      void listener() => setState(notifier);
+      notifier.addListener(listener);
+      _removeListener = () => notifier.removeListener(listener);
+    }
   }
 
   @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final provider = call(argument);
-
-    setup(origin: provider, override: provider);
-    setup(origin: provider.notifier, override: provider.notifier);
+  void runOnDispose() {
+    super.runOnDispose();
+
+    _removeListener?.call();
+    _removeListener = null;
+
+    final notifier = _notifierNotifier.result?.stateOrNull;
+    if (notifier != null) {
+      // TODO test ChangeNotifier.dispose is guarded
+      runGuarded(notifier.dispose);
+    }
+    _notifierNotifier.result = null;
   }
 
-  /// {@template riverpod.overridewithprovider}
-  /// Overrides a provider with a value, ejecting the default behaviour.
-  ///
-  /// This will also disable the auto-scoping mechanism, meaning that if the
-  /// overridden provider specified `dependencies`, it will have no effect.
-  ///
-  /// The override must not specify a `dependencies`.
-  ///
-  /// Some common use-cases are:
-  /// - testing, by replacing a service with a fake implementation, or to reach
-  ///   a very specific state easily.
-  /// - multiple environments, by changing the implementation of a class
-  ///   based on the platform or other parameters.
-  ///
-  /// This function should be used in combination with `ProviderScope.overrides`
-  /// or `ProviderContainer.overrides`:
-  ///
-  /// ```dart
-  /// final myService = Provider((ref) => MyService());
-  ///
-  /// runApp(
-  ///   ProviderScope(
-  ///     overrides: [
-  ///       myService.overrideWithProvider(
-  ///         // Replace the implementation of the provider with a different one
-  ///         Provider((ref) {
-  ///           ref.watch('other');
-  ///           return MyFakeService(),
-  ///         }),
-  ///       ),
-  ///     ],
-  ///     child: MyApp(),
-  ///   ),
-  /// );
-  /// ```
-  /// {@endtemplate}
-  Override overrideWithProvider(
-    ChangeNotifierProvider<Notifier> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(
-      this,
-      (arg, setup) {
-        final provider = call(arg);
-
-        setup(origin: provider.notifier, override: override(arg).notifier);
-        setup(origin: provider, override: provider);
-      },
+  @override
+  void visitChildren({
+    required void Function(ProviderElementBase element) elementVisitor,
+    required void Function(ProxyElementValueNotifier element) notifierVisitor,
+  }) {
+    super.visitChildren(
+      elementVisitor: elementVisitor,
+      notifierVisitor: notifierVisitor,
     );
+    notifierVisitor(_notifierNotifier);
   }
 }
+
+// ignore: subtype_of_sealed_class
+/// The [Family] of [ChangeNotifierProvider].
+class ChangeNotifierProviderFamily<NotifierT extends ChangeNotifier?, Arg>
+    extends FamilyBase<ChangeNotifierProviderRef<NotifierT>, NotifierT, Arg,
+        NotifierT, ChangeNotifierProvider<NotifierT>> {
+  /// The [Family] of [ChangeNotifierProvider].
+  ChangeNotifierProviderFamily(
+    super.create, {
+    super.name,
+    super.dependencies,
+  }) : super(providerFactory: ChangeNotifierProvider.new);
+}
diff --git a/packages/flutter_riverpod/lib/src/consumer.dart b/packages/flutter_riverpod/lib/src/consumer.dart
index def0327cd9..681956c852 100644
--- a/packages/flutter_riverpod/lib/src/consumer.dart
+++ b/packages/flutter_riverpod/lib/src/consumer.dart
@@ -129,7 +129,7 @@ abstract class WidgetRef {
   /// While more verbose than [read], using [Provider]/`select` is a lot safer.
   /// It does not rely on implementation details on `Model`, and it makes
   /// impossible to have a bug where our UI does not refresh.
-  T read<T>(ProviderBase<T> provider);
+  T read<T>(ProviderListenable<T> provider);
 
   /// Forces a provider to re-evaluate its state immediately, and return the created value.
   ///
@@ -165,7 +165,7 @@ abstract class WidgetRef {
   ///   }
   /// }
   /// ```
-  State refresh<State>(ProviderBase<State> provider);
+  State refresh<State>(Refreshable<State> provider);
 
   /// Invalidates the state of the provider, causing it to refresh.
   ///
@@ -545,12 +545,12 @@ class ConsumerStatefulElement extends StatefulElement implements WidgetRef {
   }
 
   @override
-  T read<T>(ProviderBase<T> provider) {
+  T read<T>(ProviderListenable<T> provider) {
     return ProviderScope.containerOf(this, listen: false).read(provider);
   }
 
   @override
-  State refresh<State>(ProviderBase<State> provider) {
+  State refresh<State>(Refreshable<State> provider) {
     return ProviderScope.containerOf(this, listen: false).refresh(provider);
   }
 
diff --git a/packages/flutter_riverpod/lib/src/provider_listener.dart b/packages/flutter_riverpod/lib/src/provider_listener.dart
deleted file mode 100644
index 4164e57aca..0000000000
--- a/packages/flutter_riverpod/lib/src/provider_listener.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-import 'package:flutter/widgets.dart';
-import 'package:meta/meta.dart';
-
-import 'internals.dart';
-
-/// A function that can react to changes on a provider
-///
-// ignore: deprecated_member_use_from_same_package
-/// See also [ProviderListener]
-typedef OnProviderChange<T> = void Function(
-  BuildContext context,
-  T? previous,
-  T value,
-);
-
-/// {@template riverpod.providerlistener}
-/// A widget that allows listening to a provider.
-///
-/// A common use-case is to use [ProviderListener] to push routes/modals/snackbars
-/// when the value of a provider changes.
-///
-/// Even if a provider changes many times in a quick succession, [onChange] will
-/// be called only once, at the end of the frame.
-/// {@endtemplate}
-@Deprecated('Use WidgetRef.listen instead')
-@sealed
-class ProviderListener<T> extends ConsumerWidget {
-  /// {@macro riverpod.providerlistener}
-  @Deprecated('Use WidgetRef.listen instead')
-  const ProviderListener({
-    Key? key,
-    required this.onChange,
-    required this.provider,
-    required this.child,
-  }) : super(key: key);
-
-  /// The provider listened to.
-  ///
-  /// Can be `null`.
-  final ProviderListenable<T>? provider;
-
-  /// A function called with the new value of [provider] when it changes.
-  ///
-  /// This function will be called at most once per frame.
-  final OnProviderChange<T> onChange;
-
-  /// The descendant of this [ProviderListener]
-  final Widget child;
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    if (provider != null) {
-      ref.listen<T>(
-        provider!,
-        (previous, value) => onChange(context, previous, value),
-      );
-    }
-    return child;
-  }
-}
diff --git a/packages/riverpod/CHANGELOG.md b/packages/riverpod/CHANGELOG.md
index 9d30259b3d..bb8539923c 100644
--- a/packages/riverpod/CHANGELOG.md
+++ b/packages/riverpod/CHANGELOG.md
@@ -1,8 +1,22 @@
-# Unreleased minor
+# Unreleased major
 
-- fix: StateProvider.state not respecting the `name` parameter (#1470)
+**Breaking changes**:
+
+- Using `overrideWithProvider`, it is no-longer possible to override a provider
+  with a different type of provider (such as overriding `FutureProvider` with a `StreamProvider`).
+- All `overrideWithValue` methods are removed, besides `Provider.overrideWithValue`.
+  This change is temporary, and these methods will be reintroduced in a later version.
+- Modifiers (`provider.future`, `provider.state`, ...) no-longer are providers, and therefore no-longer
+  appears inside `ProviderObserver`.
+- The `Reader` typedef is removed. Use `Ref` instead.
+- `ProviderListener` is removed. Used `ref.listen` instead.
+
+Non breaking changes:
+
+- feat: A new `AutoDisposeRef.keepAlive()` function is added. It is meant to replace
+  `AutoDisposeRef.maintainState` to make logic for preventing the disposal of a provider more reusable.
+- `AutoDisposeRef.maintainState` is deprecated. Use the new ``AutoDisposeRef.keepAlive()` instead.
 - feat: Add support for `ref.invalidate(family)` to recompiute an entire family (#1517)
-- `Reader` is now marked as deprecated.
 
 # 2.0.0-dev.9
 
diff --git a/packages/riverpod/lib/riverpod.dart b/packages/riverpod/lib/riverpod.dart
index 9ed2d0accb..572c89c77b 100644
--- a/packages/riverpod/lib/riverpod.dart
+++ b/packages/riverpod/lib/riverpod.dart
@@ -1,16 +1,11 @@
 export 'package:state_notifier/state_notifier.dart' hide Listener, LocatorMixin;
 
-export 'src/async_value_converters.dart'
-    show AlwaysAliveAsyncProviderX, AutoDisposeAsyncProviderX;
-
 export 'src/common.dart'
     show AsyncValue, AsyncData, AsyncLoading, AsyncError, AsyncValueX;
 
 export 'src/framework.dart'
     show
         Create,
-        // ignore: deprecated_member_use_from_same_package
-        Reader,
         AlwaysAliveProviderBase,
         Family,
         CircularDependencyError,
@@ -22,20 +17,18 @@ export 'src/framework.dart'
         ProviderContainer,
         ProviderObserver,
         ProviderSubscription,
-        AutoDisposeProviderBase,
-        AutoDisposeProviderElementBase,
+        AutoDisposeProviderElementMixin,
         ProviderElementBase,
         ProviderOverride,
         FamilyOverride,
         SetupOverride,
         AlwaysAliveProviderListenable,
         FamilyCreate,
-        XAutoDisposeFamily,
-        XFamily,
-        AsyncSelector,
-        AlwaysAliveAsyncSelector,
         KeepAliveLink,
-        ProviderOrFamily;
+        ProviderOrFamily,
+        OverrideWithProviderExtension,
+        AlwaysAliveRefreshable,
+        Refreshable;
 
 export 'src/future_provider.dart'
     show
@@ -44,7 +37,9 @@ export 'src/future_provider.dart'
         FutureProvider,
         FutureProviderFamily,
         AutoDisposeFutureProviderRef,
-        FutureProviderRef;
+        FutureProviderRef,
+        AutoDisposeFutureProviderElement,
+        FutureProviderElement;
 
 export 'src/provider.dart'
     show
@@ -57,6 +52,8 @@ export 'src/provider.dart'
         AutoDisposeProviderElement,
         ProviderElement;
 
+export 'src/state_controller.dart' show StateController;
+
 export 'src/state_notifier_provider.dart'
     show
         AutoDisposeStateNotifierProvider,
@@ -65,11 +62,11 @@ export 'src/state_notifier_provider.dart'
         StateNotifierProviderFamily,
         AutoDisposeStateNotifierProviderRef,
         StateNotifierProviderRef,
-        StateNotifierProviderOverrideMixin;
+        AutoDisposeStateNotifierProviderElement,
+        StateNotifierProviderElement;
 
 export 'src/state_provider.dart'
     show
-        StateController,
         StateProvider,
         AutoDisposeStateProvider,
         AutoDisposeStateProviderFamily,
@@ -86,4 +83,6 @@ export 'src/stream_provider.dart'
         StreamProvider,
         StreamProviderFamily,
         AutoDisposeStreamProviderRef,
-        StreamProviderRef;
+        StreamProviderRef,
+        AutoDisposeStreamProviderElement,
+        StreamProviderElement;
diff --git a/packages/riverpod/lib/src/async_value_converters.dart b/packages/riverpod/lib/src/async_value_converters.dart
deleted file mode 100644
index 29d9ccaa26..0000000000
--- a/packages/riverpod/lib/src/async_value_converters.dart
+++ /dev/null
@@ -1,487 +0,0 @@
-import 'dart:async';
-
-import 'package:meta/meta.dart';
-
-import 'internals.dart';
-
-/// Adds [future] and [stream] to providers that emit an [AsyncValue]
-extension AlwaysAliveAsyncProviderX<State>
-    on AlwaysAliveProviderBase<AsyncValue<State>> {
-  /// {@template riverpod.asyncprovider.future}
-  /// Exposes a [Future] that resolves with the last value or error emitted.
-  ///
-  /// This can be useful for scenarios where we want to read the current value
-  /// exposed by a [StreamProvider], but also handle the scenario were no
-  /// value were emitted yet:
-  ///
-  /// ```dart
-  /// final configsProvider = StreamProvider<Configuration>((ref) async* {
-  ///   // somehow emit a Configuration instance
-  /// });
-  ///
-  /// final productsProvider = FutureProvider<Products>((ref) async {
-  ///   // If a "Configuration" was emitted, retrieve it.
-  ///   // Otherwise, wait for a Configuration to be emitted.
-  ///   final configs = await ref.watch(configsProvider.future);
-  ///
-  ///   final response = await httpClient.get('${configs.host}/products');
-  ///   return Products.fromJson(response.data);
-  /// });
-  /// ```
-  ///
-  /// ## Why not use [StreamProvider.stream.first] instead?
-  ///
-  /// If you are familiar with streams, you may wonder why not use [Stream.first]
-  /// instead:
-  ///
-  /// ```dart
-  /// final configsProvider = StreamProvider<Configuration>((ref) {...});
-  ///
-  /// final productsProvider = FutureProvider<Products>((ref) async {
-  ///   final configs = await ref.watch(configsProvider.stream).first;
-  ///   ...
-  /// }
-  /// ```
-  ///
-  /// The problem with this code is, unless your [StreamProvider] is creating
-  /// a `BehaviorSubject` from `package:rxdart`, you have a bug.
-  ///
-  /// By default, if we call [Stream.first] **after** the first value was emitted,
-  /// then the [Future] created will not obtain that first value but instead
-  /// wait for a second one – which may never come.
-  ///
-  /// The following code demonstrate this problem:
-  ///
-  /// ```dart
-  /// final exampleProvider = StreamProvider<int>((ref) async* {
-  ///   yield 42;
-  /// });
-  ///
-  /// final anotherProvider = FutureProvider<void>((ref) async {
-  ///   print(await ref.watch(exampleProvider.stream).first);
-  ///   // The code will block here and wait forever
-  ///   print(await ref.watch(exampleProvider.stream).first);
-  ///   print('this code is never reached');
-  /// });
-  ///
-  /// void main() async {
-  ///   final container = ProviderContainer();
-  ///   await container.read(anotherProvider.future);
-  ///   // never reached
-  ///   print('done');
-  /// }
-  /// ```
-  ///
-  /// This snippet will print `42` once, then wait forever.
-  ///
-  /// On the other hand, if we used [future], our code would
-  /// correctly execute:
-  ///
-  /// ```dart
-  /// final exampleProvider = StreamProvider<int>((ref) async* {
-  ///   yield 42;
-  /// });
-  ///
-  /// final anotherProvider = FutureProvider<void>((ref) async {
-  ///   print(await ref.watch(exampleProvider.future));
-  ///   print(await ref.watch(exampleProvider.future));
-  ///   print('completed');
-  /// });
-  ///
-  /// void main() async {
-  ///   final container = ProviderContainer();
-  ///   await container.read(anotherProvider.future);
-  ///   print('done');
-  /// }
-  /// ```
-  ///
-  /// with this modification, our code will now print:
-  ///
-  /// ```
-  /// 42
-  /// 42
-  /// completed
-  /// done
-  /// ```
-  ///
-  /// which is the expected behavior.
-  /// {@endtemplate}
-  AlwaysAliveProviderBase<Future<State>> get future =>
-      AsyncValueAsFutureProvider(this, from: from, argument: argument);
-
-  /// {@template riverpod.asyncprovider.stream}
-  /// Converts the provider into a stream.
-  ///
-  /// If the transformed provider created a stream, it is important to keep in mind
-  /// that the stream obtained and the stream created will be different.
-  ///
-  /// The stream obtained may change over time if the provider is
-  /// re-evaluated, such as when it is using [Ref.watch] and the
-  /// provider being listened to changes, or on [ProviderContainer.refresh].
-  ///
-  /// If the provider was overridden using `overrideWithValue`,
-  /// a stream will be generated and manipulated based on the [AsyncValue] used.
-  /// {@endtemplate}
-  AlwaysAliveProviderBase<Stream<State>> get stream =>
-      AsyncValueAsStreamProvider(this, from: from, argument: argument);
-}
-
-/// Adds [future] and [stream] to autoDispose providers that emit an [AsyncValue]
-extension AutoDisposeAsyncProviderX<State>
-    on AutoDisposeProviderBase<AsyncValue<State>> {
-  /// {@macro riverpod.asyncprovider.future}
-  AutoDisposeProviderBase<Future<State>> get future =>
-      AutoDisposeAsyncValueAsFutureProvider(
-        this,
-        from: from,
-        argument: argument,
-        cacheTime: cacheTime,
-        disposeDelay: disposeDelay,
-      );
-
-  /// {@macro riverpod.asyncprovider.stream}
-  AutoDisposeProviderBase<Stream<State>> get stream =>
-      AutoDisposeAsyncValueAsStreamProvider(
-        this,
-        from: from,
-        argument: argument,
-        cacheTime: cacheTime,
-        disposeDelay: disposeDelay,
-      );
-}
-
-///
-@protected
-class AsyncValueAsStreamProvider<State>
-    extends AlwaysAliveProviderBase<Stream<State>> {
-  ///
-  AsyncValueAsStreamProvider(
-    this._provider, {
-    required Family? from,
-    required Object? argument,
-  }) : super(
-          name: modifierName(_provider.name, 'stream'),
-          from: from,
-          argument: argument,
-        );
-
-  final AlwaysAliveProviderBase<AsyncValue<State>> _provider;
-
-  @override
-  late final List<ProviderOrFamily>? dependencies = [_provider];
-
-  @override
-  ProviderBase<Object?> get originProvider => _provider;
-
-  @override
-  Stream<State> create(covariant ProviderElementBase<Stream<State>> ref) {
-    return _asyncValueToStream(_provider, ref);
-  }
-
-  @override
-  ProviderElement<Stream<State>> createElement() {
-    return ProviderElement(this);
-  }
-
-  @override
-  bool updateShouldNotify(
-    Stream<State> previousState,
-    Stream<State> newState,
-  ) {
-    return true;
-  }
-
-  @override
-  // ignore: avoid_equals_and_hash_code_on_mutable_classes
-  bool operator ==(Object other) {
-    return other is AsyncValueAsStreamProvider<State> &&
-        other._provider == _provider;
-  }
-
-  @override
-  // ignore: avoid_equals_and_hash_code_on_mutable_classes
-  int get hashCode => _provider.hashCode;
-}
-
-///
-@protected
-class AutoDisposeAsyncValueAsStreamProvider<State>
-    extends AutoDisposeProviderBase<Stream<State>> {
-  ///
-  AutoDisposeAsyncValueAsStreamProvider(
-    this._provider, {
-    required Family? from,
-    required Object? argument,
-    required Duration? cacheTime,
-    required Duration? disposeDelay,
-  }) : super(
-          name: modifierName(_provider.name, 'stream'),
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final AutoDisposeProviderBase<AsyncValue<State>> _provider;
-
-  @override
-  late final List<ProviderOrFamily>? dependencies = [_provider];
-
-  @override
-  ProviderBase<Object?> get originProvider => _provider;
-
-  @override
-  Stream<State> create(
-      covariant AutoDisposeProviderElementBase<Stream<State>> ref) {
-    return _asyncValueToStream(_provider, ref);
-  }
-
-  @override
-  AutoDisposeProviderElement<Stream<State>> createElement() {
-    return AutoDisposeProviderElement(this);
-  }
-
-  @override
-  bool updateShouldNotify(
-    Stream<State> previousState,
-    Stream<State> newState,
-  ) {
-    return true;
-  }
-
-  @override
-  // ignore: avoid_equals_and_hash_code_on_mutable_classes
-  bool operator ==(Object other) {
-    return other is AutoDisposeAsyncValueAsStreamProvider<State> &&
-        other._provider == _provider;
-  }
-
-  @override
-  // ignore: avoid_equals_and_hash_code_on_mutable_classes
-  int get hashCode => _provider.hashCode;
-}
-
-Stream<State> _asyncValueToStream<State>(
-  ProviderBase<AsyncValue<State>> provider,
-  ProviderElementBase<Stream<State>> ref,
-) {
-  StreamController<State>? controller;
-
-  StreamController<State> getController() {
-    if (controller == null) {
-      // Using a non-broadcast controller followed by asBroadcastStream instead
-      // of directly creating a broadcast controller so that `add`/`addError` calls
-      // are queued. This ensures that listeners will properly receive the first value.
-      controller = StreamController<State>();
-      ref.setState(
-        controller!.stream.asBroadcastStream(
-          onListen: (sub) => sub.resume(),
-          onCancel: (sub) => sub.pause(),
-        ),
-      );
-    }
-    return controller!;
-  }
-
-  ref.onDispose(() => controller?.close());
-
-  void listener(AsyncValue<State>? previous, AsyncValue<State> value) {
-    if (value.isLoading || value.isRefreshing) {
-      controller?.close();
-      controller = null;
-      // will call ref.state =
-      getController();
-    }
-
-    value.map(
-      loading: (_) {
-        // already taken care of above
-      },
-      data: (value) {
-        if (!value.isRefreshing) getController().add(value.value);
-      },
-      error: (value) {
-        if (!value.isRefreshing) {
-          getController().addError(value.error, value.stackTrace);
-        }
-      },
-    );
-  }
-
-  ref.listen<AsyncValue<State>>(provider, listener, fireImmediately: true);
-
-  return ref.requireState;
-}
-
-///
-@protected
-class AsyncValueAsFutureProvider<State>
-    extends AlwaysAliveProviderBase<Future<State>> {
-  ///
-  AsyncValueAsFutureProvider(
-    this._provider, {
-    required Family? from,
-    required Object? argument,
-  }) : super(
-          name: modifierName(_provider.name, 'future'),
-          from: from,
-          argument: argument,
-        );
-
-  final AlwaysAliveProviderBase<AsyncValue<State>> _provider;
-
-  @override
-  late final List<ProviderOrFamily>? dependencies = [_provider];
-
-  @override
-  ProviderBase<Object?> get originProvider => _provider;
-
-  @override
-  Future<State> create(ProviderElementBase<Future<State>> ref) {
-    return _asyncValueAsFuture(_provider, ref);
-  }
-
-  @override
-  bool updateShouldNotify(
-    Future<State> previousState,
-    Future<State> newState,
-  ) {
-    return true;
-  }
-
-  @override
-  ProviderElement<Future<State>> createElement() {
-    return ProviderElement(this);
-  }
-
-  @override
-  // ignore: avoid_equals_and_hash_code_on_mutable_classes
-  bool operator ==(Object other) {
-    return other is AsyncValueAsFutureProvider<State> &&
-        other._provider == _provider;
-  }
-
-  @override
-  // ignore: avoid_equals_and_hash_code_on_mutable_classes
-  int get hashCode => _provider.hashCode;
-}
-
-///
-@protected
-class AutoDisposeAsyncValueAsFutureProvider<State>
-    extends AutoDisposeProviderBase<Future<State>> {
-  ///
-  AutoDisposeAsyncValueAsFutureProvider(
-    this._provider, {
-    required Family? from,
-    required Object? argument,
-    required Duration? cacheTime,
-    required Duration? disposeDelay,
-  }) : super(
-          name: modifierName(_provider.name, 'future'),
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final AutoDisposeProviderBase<AsyncValue<State>> _provider;
-
-  @override
-  late final List<ProviderOrFamily>? dependencies = [_provider];
-
-  @override
-  ProviderBase<Object?> get originProvider => _provider;
-
-  @override
-  Future<State> create(AutoDisposeProviderElementBase<Future<State>> ref) {
-    return _asyncValueAsFuture(_provider, ref);
-  }
-
-  @override
-  bool updateShouldNotify(
-    Future<State> previousState,
-    Future<State> newState,
-  ) {
-    return true;
-  }
-
-  @override
-  AutoDisposeProviderElement<Future<State>> createElement() {
-    return AutoDisposeProviderElement(this);
-  }
-
-  @override
-  // ignore: avoid_equals_and_hash_code_on_mutable_classes
-  bool operator ==(Object other) {
-    return other is AutoDisposeAsyncValueAsFutureProvider<State> &&
-        other._provider == _provider;
-  }
-
-  @override
-  // ignore: avoid_equals_and_hash_code_on_mutable_classes
-  int get hashCode => _provider.hashCode;
-}
-
-Future<State> _asyncValueAsFuture<State>(
-  ProviderBase<AsyncValue<State>> provider,
-  ProviderElementBase<Future<State>> ref,
-) {
-  Completer<State>? loadingCompleter;
-
-  ref.onDispose(() {
-    if (loadingCompleter != null) {
-      loadingCompleter!.completeError(
-        StateError(
-          'The provider $provider was disposed before a value was emitted.',
-        ),
-      );
-    }
-  });
-
-  void listener(AsyncValue<State>? previous, AsyncValue<State> value) {
-    if (value.isLoading || value.isRefreshing) {
-      if (loadingCompleter == null) {
-        loadingCompleter = Completer<State>();
-        ref.setState(
-          // TODO test ignore
-          loadingCompleter!.future..ignore(),
-        );
-      }
-    }
-
-    value.map(
-      loading: (_) {
-        // already taken care of above
-      },
-      data: (data) {
-        // already taken care of above
-        if (data.isRefreshing) return;
-
-        if (loadingCompleter != null) {
-          loadingCompleter!.complete(data.value);
-          // allow follow-up data calls to go on the 'else' branch
-          loadingCompleter = null;
-        } else {
-          ref.setState(Future<State>.value(data.value));
-        }
-      },
-      error: (error) {
-        // already taken care of above
-        if (error.isRefreshing) return;
-
-        if (loadingCompleter != null) {
-          loadingCompleter!.completeError(error.error, error.stackTrace);
-          // allow follow-up error calls to go on the 'else' branch
-          loadingCompleter = null;
-        } else {
-          ref.setState(Future<State>.error(error.error, error.stackTrace));
-        }
-      },
-    );
-  }
-
-  ref.listen<AsyncValue<State>>(provider, listener, fireImmediately: true);
-
-  return ref.requireState;
-}
diff --git a/packages/riverpod/lib/src/common.dart b/packages/riverpod/lib/src/common.dart
index 1617c84045..0889967d54 100644
--- a/packages/riverpod/lib/src/common.dart
+++ b/packages/riverpod/lib/src/common.dart
@@ -4,11 +4,6 @@ import 'future_provider.dart' show FutureProvider;
 import 'stack_trace.dart';
 import 'stream_provider.dart' show StreamProvider;
 
-/// Utility for `.name` of provider modifiers.
-String? modifierName(String? from, String modifier) {
-  return from == null ? null : '$from.$modifier';
-}
-
 /// A utility for safely manipulating asynchronous data.
 ///
 /// By using [AsyncValue], you are guaranteed that you cannot forget to
diff --git a/packages/riverpod/lib/src/devtool.dart b/packages/riverpod/lib/src/devtool.dart
index 51ee9e0451..105c94d7da 100644
--- a/packages/riverpod/lib/src/devtool.dart
+++ b/packages/riverpod/lib/src/devtool.dart
@@ -1,6 +1,10 @@
 // ignore_for_file: public_member_api_docs
 
-part of 'provider.dart';
+import 'dart:developer' as developer;
+
+import 'package:meta/meta.dart';
+
+import 'framework.dart';
 
 void Function(
   String eventKind,
diff --git a/packages/riverpod/lib/src/framework.dart b/packages/riverpod/lib/src/framework.dart
index a2dde97680..842737547d 100644
--- a/packages/riverpod/lib/src/framework.dart
+++ b/packages/riverpod/lib/src/framework.dart
@@ -4,6 +4,8 @@ import 'dart:async';
 import 'dart:collection';
 
 import 'package:meta/meta.dart';
+import 'package:state_notifier/state_notifier.dart';
+import 'devtool.dart';
 import 'internals.dart';
 import 'stack_trace.dart';
 
@@ -11,10 +13,12 @@ part 'framework/always_alive.dart';
 part 'framework/auto_dispose.dart';
 part 'framework/async_selector.dart';
 part 'framework/provider_base.dart';
+part 'framework/element.dart';
 part 'framework/container.dart';
 part 'framework/family.dart';
 part 'framework/listen.dart';
 part 'framework/foundation.dart';
+part 'framework/proxy_provider_listenable.dart';
 part 'framework/ref.dart';
 part 'framework/selector.dart';
 part 'framework/scheduler.dart';
diff --git a/packages/riverpod/lib/src/framework/always_alive.dart b/packages/riverpod/lib/src/framework/always_alive.dart
index c6190fe3e8..cd951a4547 100644
--- a/packages/riverpod/lib/src/framework/always_alive.dart
+++ b/packages/riverpod/lib/src/framework/always_alive.dart
@@ -22,18 +22,17 @@ mixin AlwaysAliveProviderListenable<State> on ProviderListenable<State> {
 ///
 /// This is the default base class for providers, unless a provider was marked
 /// with the `.autoDispose` modifier, like: `Provider.autoDispose(...)`
-abstract class AlwaysAliveProviderBase<State> extends ProviderBase<State>
-    with AlwaysAliveProviderListenable<State> {
-  /// Creates an [AlwaysAliveProviderBase].
-  AlwaysAliveProviderBase({
-    required String? name,
-    required Family? from,
-    required Object? argument,
-  }) : super(name: name, from: from, argument: argument);
-
+mixin AlwaysAliveProviderBase<State> on ProviderBase<State>
+    implements
+        AlwaysAliveProviderListenable<State>,
+        AlwaysAliveRefreshable<State> {
   @override
-  ProviderElementBase<State> createElement();
+  AlwaysAliveProviderListenable<Selected> select<Selected>(
+    Selected Function(State value) selector,
+  ) {
+    return _AlwaysAliveProviderSelector<State, Selected>(
+      provider: this,
+      selector: selector,
+    );
+  }
 }
-
-class _AlwaysAliveProviderSelector<Input, Output> = _ProviderSelector<Input,
-    Output> with AlwaysAliveProviderListenable<Output>;
diff --git a/packages/riverpod/lib/src/framework/async_selector.dart b/packages/riverpod/lib/src/framework/async_selector.dart
index a82fa77429..74ea46451a 100644
--- a/packages/riverpod/lib/src/framework/async_selector.dart
+++ b/packages/riverpod/lib/src/framework/async_selector.dart
@@ -1,7 +1,10 @@
 part of '../framework.dart';
 
 /// Adds [selectAsync] to [ProviderListenable]
-extension AsyncSelector<Input> on ProviderListenable<AsyncValue<Input>> {
+mixin AsyncSelector<Input> on ProviderListenable<AsyncValue<Input>> {
+  /// The future that [selectAsync] will query
+  ProviderListenable<Future<Input>> get future;
+
   /// {@template riverpod.async_select}
   /// A variant of [select] for asynchronous values
   ///
@@ -34,18 +37,29 @@ extension AsyncSelector<Input> on ProviderListenable<AsyncValue<Input>> {
   ProviderListenable<Future<Output>> selectAsync<Output>(
     Output Function(Input data) selector,
   ) {
-    return _AlwaysAliveAsyncSelector(selector: selector, provider: this);
+    return _AlwaysAliveAsyncSelector(
+      selector: selector,
+      provider: this,
+      future: future,
+    );
   }
 }
 
 /// Adds [selectAsync] to [AlwaysAliveProviderListenable]
-extension AlwaysAliveAsyncSelector<Input>
+mixin AlwaysAliveAsyncSelector<Input>
     on AlwaysAliveProviderListenable<AsyncValue<Input>> {
+  /// The future that [selectAsync] will query
+  AlwaysAliveProviderListenable<Future<Input>> get future;
+
   /// {@macro riverpod.async_select}
   AlwaysAliveProviderListenable<Future<Output>> selectAsync<Output>(
     Output Function(Input data) selector,
   ) {
-    return _AlwaysAliveAsyncSelector(selector: selector, provider: this);
+    return _AlwaysAliveAsyncSelector(
+      selector: selector,
+      provider: this,
+      future: future,
+    );
   }
 }
 
@@ -58,12 +72,16 @@ class _AsyncSelector<Input, Output> with ProviderListenable<Future<Output>> {
   /// An internal class for `ProviderBase.select`.
   _AsyncSelector({
     required this.provider,
+    required this.future,
     required this.selector,
   });
 
   /// The provider that was selected
   final ProviderListenable<AsyncValue<Input>> provider;
 
+  /// The future associated to the listened provider
+  final ProviderListenable<Future<Input>> future;
+
   /// The selector applied
   final Output Function(Input) selector;
 
@@ -89,8 +107,9 @@ class _AsyncSelector<Input, Output> with ProviderListenable<Future<Output>> {
   _SelectorSubscription<AsyncValue<Input>, Future<Output>> addListener(
     Node node,
     void Function(Future<Output>? previous, Future<Output> next) listener, {
-    void Function(Object error, StackTrace stackTrace)? onError,
-    bool fireImmediately = false,
+    required void Function(Object error, StackTrace stackTrace)? onError,
+    required void Function()? onDependencyMayHaveChanged,
+    required bool fireImmediately,
   }) {
     Result<Output>? lastSelectedValue;
     Completer<Output>? selectedCompleter;
@@ -208,4 +227,7 @@ class _AsyncSelector<Input, Output> with ProviderListenable<Future<Output>> {
       () => selectedFuture!,
     );
   }
+
+  @override
+  Future<Output> read(Node node) => future.read(node).then(selector);
 }
diff --git a/packages/riverpod/lib/src/framework/auto_dispose.dart b/packages/riverpod/lib/src/framework/auto_dispose.dart
index 6dc079431a..2a5f632286 100644
--- a/packages/riverpod/lib/src/framework/auto_dispose.dart
+++ b/packages/riverpod/lib/src/framework/auto_dispose.dart
@@ -1,117 +1,11 @@
 part of '../framework.dart';
 
-/// A [Ref] for providers that are automatically destroyed when
-/// no longer used.
-///
-/// The difference with [Ref] is that it has an extra
-/// [keepAlive] function to help determine if the state can be destroyed
-///  or not.
-abstract class AutoDisposeRef<State> extends Ref<State> {
-  /// Whether to destroy the state of the provider when all listeners are removed or not.
-  ///
-  /// Can be changed at any time, in which case when setting it to `false`,
-  /// may destroy the provider state if it currently has no listeners.
-  ///
-  /// Defaults to `false`.
-  @Deprecated('use keepAlive() instead')
-  bool get maintainState;
-
-  @Deprecated('use keepAlive() instead')
-  set maintainState(bool value);
-
-  /// Requests for the state of a provider to not be disposed when all the
-  /// listeners of the provider are removed.
-  ///
-  /// Returns an object which allows cancelling this operation, therefore
-  /// allowing the provider to dispose itself when all listeners are removed.
-  ///
-  /// If [keepAlive] is invoked multiple times, all [KeepAliveLink] will have
-  /// to be closed for the provider to dispose itself when all listeners are removed.
-  KeepAliveLink keepAlive();
-
-  @override
-  T watch<T>(
-    // can watch both auto-dispose and non-auto-dispose providers
-    ProviderListenable<T> provider,
-  );
-
-  @override
-  ProviderSubscription<T> listen<T>(
-    // overridden to allow AutoDisposeProviderBase
-    ProviderListenable<T> provider,
-    void Function(T? previous, T next) listener, {
-    bool fireImmediately,
-    void Function(Object error, StackTrace stackTrace)? onError,
-  });
-}
-
-/// {@template riverpod.AutoDisposeProviderBase}
-/// A base class for providers that destroy their state when no longer listened to.
-///
-/// See also:
-///
-/// - [Provider.autoDispose], a variant of [Provider] that auto-dispose its state.
-/// {@endtemplate}
-abstract class AutoDisposeProviderBase<State> extends ProviderBase<State> {
-  /// {@macro riverpod.AutoDisposeProviderBase}
-  AutoDisposeProviderBase({
-    required String? name,
-    required Family? from,
-    required Object? argument,
-    required this.cacheTime,
-    required this.disposeDelay,
-  }) : super(name: name, from: from, argument: argument);
-
-  /// {@template riverpod.cache_time}
-  /// The minimum amount of time before an `autoDispose` provider can be
-  /// disposed if not listened after the last value change.
-  ///
-  /// If the provider rebuilds (such as when using `ref.watch` or `ref.refresh`)
-  /// or emits a new value, the timer will be refreshed.
-  ///
-  /// If null, use the nearest ancestor [ProviderContainer]'s [cacheTime].
-  /// If no ancestor is found, fallbacks to [Duration.zero].
-  /// {@endtemplate}
-  final Duration? cacheTime;
-
-  /// {@template riverpod.dispose_delay}
-  /// The amount of time before a provider is disposed after its last listener
-  /// is removed.
-  ///
-  /// If a new listener is added within that duration, the provider will not be
-  /// disposed.
-  ///
-  /// If null, use the nearest ancestor [ProviderContainer]'s [disposeDelay].
-  /// If no ancestor is found, fallbacks to [Duration.zero].
-  /// {@endtemplate}
-  final Duration? disposeDelay;
-
-  @override
-  State create(AutoDisposeRef ref);
-
-  @override
-  AutoDisposeProviderElementBase<State> createElement();
-}
-
-/// The [ProviderElementBase] of an [AutoDisposeProviderBase].
-abstract class AutoDisposeProviderElementBase<State>
-    extends ProviderElementBase<State> implements AutoDisposeRef<State> {
-  /// The [ProviderElementBase] of an [AutoDisposeProviderBase].
-  AutoDisposeProviderElementBase(ProviderBase<State> provider)
-      : super(provider);
-
-  // TODO make nullable
-  final _keepAliveLinks = <KeepAliveLink>[];
+/// A mixin that adds auto dispose support to a [ProviderElementBase].
+mixin AutoDisposeProviderElementMixin<State> on ProviderElementBase<State>
+    implements AutoDisposeRef<State> {
+  List<KeepAliveLink>? _keepAliveLinks;
 
   bool _maintainState = false;
-
-  late final _cacheTime =
-      (provider as AutoDisposeProviderBase).cacheTime ?? _container.cacheTime;
-
-  late final _disposeDelay =
-      (provider as AutoDisposeProviderBase).disposeDelay ??
-          _container.disposeDelay;
-
   @Deprecated('Use `keepAlive()` instead')
   @override
   bool get maintainState => _maintainState;
@@ -121,36 +15,42 @@ abstract class AutoDisposeProviderElementBase<State>
     if (!value) mayNeedDispose();
   }
 
-  Timer? _cacheTimer;
+  late final _cacheTime = provider.cacheTime ?? _container.cacheTime;
+
+  late final _disposeDelay = provider.disposeDelay ?? _container.disposeDelay;
 
+  Timer? _cacheTimer;
   KeepAliveLink? _disposeDelayLink;
   Timer? _disposeDelayTimer;
 
   @override
   KeepAliveLink keepAlive() {
-    late KeepAliveLink link;
+    final links = _keepAliveLinks ??= [];
 
+    late KeepAliveLink link;
     link = KeepAliveLink._(() {
-      if (_keepAliveLinks.remove(link)) {
-        if (_keepAliveLinks.isEmpty) mayNeedDispose();
+      if (links.remove(link)) {
+        if (links.isEmpty) mayNeedDispose();
       }
     });
-    _keepAliveLinks.add(link);
+    links.add(link);
 
     return link;
   }
 
   @override
   void mayNeedDispose() {
+    final links = _keepAliveLinks;
+
     // ignore: deprecated_member_use_from_same_package
-    if (!maintainState && !hasListeners && _keepAliveLinks.isEmpty) {
+    if (!maintainState && !hasListeners && (links == null || links.isEmpty)) {
       _container._scheduler.scheduleProviderDispose(this);
     }
   }
 
   @override
-  void _buildState() {
-    super._buildState();
+  void buildState() {
+    super.buildState();
 
     if (_disposeDelay != Duration.zero) {
       // TODO timer should not refresh when provider rebuilds
@@ -161,7 +61,8 @@ abstract class AutoDisposeProviderElementBase<State>
       // new one
       assert(
         _disposeDelayLink == null ||
-            !_keepAliveLinks.contains(_disposeDelayLink),
+            _keepAliveLinks == null ||
+            !_keepAliveLinks!.contains(_disposeDelayLink),
         'Bad state',
       );
       _disposeDelayLink = keepAlive();
@@ -228,11 +129,11 @@ abstract class AutoDisposeProviderElementBase<State>
   }
 
   @override
-  void _runOnDispose() {
-    _keepAliveLinks.clear();
-    super._runOnDispose();
+  void runOnDispose() {
+    _keepAliveLinks?.clear();
+    super.runOnDispose();
     assert(
-      _keepAliveLinks.isEmpty,
+      _keepAliveLinks == null || _keepAliveLinks!.isEmpty,
       'Cannot call keepAlive() within onDispose listeners',
     );
   }
diff --git a/packages/riverpod/lib/src/framework/container.dart b/packages/riverpod/lib/src/framework/container.dart
index 3410e03fa7..64547b929c 100644
--- a/packages/riverpod/lib/src/framework/container.dart
+++ b/packages/riverpod/lib/src/framework/container.dart
@@ -1,56 +1,5 @@
 part of '../framework.dart';
 
-void _runGuarded(void Function() cb) {
-  try {
-    cb();
-  } catch (err, stack) {
-    Zone.current.handleUncaughtError(err, stack);
-  }
-}
-
-void _runUnaryGuarded<T, Res>(Res Function(T) cb, T value) {
-  try {
-    cb(value);
-  } catch (err, stack) {
-    Zone.current.handleUncaughtError(err, stack);
-  }
-}
-
-void _runBinaryGuarded<A, B>(void Function(A, B) cb, A value, B value2) {
-  try {
-    cb(value, value2);
-  } catch (err, stack) {
-    Zone.current.handleUncaughtError(err, stack);
-  }
-}
-
-void _runTernaryGuarded<A, B, C>(
-  void Function(A, B, C) cb,
-  A value,
-  B value2,
-  C value3,
-) {
-  try {
-    cb(value, value2, value3);
-  } catch (err, stack) {
-    Zone.current.handleUncaughtError(err, stack);
-  }
-}
-
-void _runQuaternaryGuarded<A, B, C, D>(
-  void Function(A, B, C, D) cb,
-  A value,
-  B value2,
-  C value3,
-  D value4,
-) {
-  try {
-    cb(value, value2, value3, value4);
-  } catch (err, stack) {
-    Zone.current.handleUncaughtError(err, stack);
-  }
-}
-
 ProviderBase? _circularDependencyLock;
 
 void _defaultVsync(void Function() task) {
@@ -107,7 +56,7 @@ class _StateReader {
         // ignore: avoid_types_on_closure_parameters
         data: (ResultData<Object?> data) {
           for (final observer in container._observers) {
-            _runTernaryGuarded(
+            runTernaryGuarded(
               observer.didAddProvider,
               origin,
               data.state,
@@ -117,7 +66,7 @@ class _StateReader {
         },
         error: (error) {
           for (final observer in container._observers) {
-            _runTernaryGuarded(
+            runTernaryGuarded(
               observer.didAddProvider,
               origin,
               null,
@@ -125,7 +74,7 @@ class _StateReader {
             );
           }
           for (final observer in container._observers) {
-            _runQuaternaryGuarded(
+            runQuaternaryGuarded(
               observer.providerDidFail,
               origin,
               error.error,
@@ -209,12 +158,12 @@ class ProviderContainer implements Node {
     }
   }
 
-  /// The default value for [AutoDisposeProviderBase.cacheTime].
+  /// The default value for [ProviderBase.cacheTime].
   ///
   /// {@macro riverpod.cache_time}
   final Duration cacheTime;
 
-  /// The default value for [AutoDisposeProviderBase.disposeDelay].
+  /// The default value for [ProviderBase.disposeDelay].
   ///
   /// {@macro riverpod.dispose_delay}
   final Duration disposeDelay;
@@ -303,30 +252,24 @@ class ProviderContainer implements Node {
   /// }
   /// ```
   Result read<Result>(
-    ProviderBase<Result> provider,
+    ProviderListenable<Result> provider,
   ) {
-    final element = readProviderElement(provider);
-    element.flush();
-
-    // In case `read` was called on a provider that has no listener
-    element.mayNeedDispose();
-
-    return element.readSelf();
+    return provider.read(this);
   }
 
   @override
-  ProviderSubscription<State> _createSubscription<State>(
+  ProviderSubscription<State> _listenElement<State>(
     ProviderElementBase<State> element, {
     required void Function(State? previous, State next) listener,
     required void Function(Object error, StackTrace stackTrace) onError,
   }) {
-    final sub = _ProviderSubscription<State>._(
+    final sub = _ExternalProviderSubscription<State>._(
       element,
       listener,
       onError: onError,
     );
 
-    element._listeners.add(sub);
+    element._externalDependents.add(sub);
 
     return sub;
   }
@@ -345,13 +288,14 @@ class ProviderContainer implements Node {
       listener,
       fireImmediately: fireImmediately,
       onError: onError,
+      onDependencyMayHaveChanged: null,
     );
   }
 
   /// {@template riverpod.invalidate}
   void invalidate(ProviderOrFamily provider) {
     if (provider is ProviderBase) {
-      final reader = _getStateReader(provider.originProvider);
+      final reader = _getStateReader(provider._origin);
 
       reader._element?.invalidateSelf();
     } else {
@@ -368,8 +312,8 @@ class ProviderContainer implements Node {
   }
 
   /// {@template riverpod.refresh}
-  Created refresh<Created>(ProviderBase<Created> provider) {
-    invalidate(provider);
+  State refresh<State>(Refreshable<State> provider) {
+    invalidate(provider._origin);
     return read(provider);
   }
 
@@ -448,7 +392,7 @@ class ProviderContainer implements Node {
         final element = reader._element;
         if (element == null) continue;
 
-        _runUnaryGuarded(element.update, override._override);
+        runUnaryGuarded(element.update, override._override);
       } else if (override is FamilyOverride) {
         assert(() {
           unusedOverrides!.remove(override);
@@ -734,19 +678,23 @@ final b = Provider((ref) => ref.watch(a), dependencies: [a]);
       // were already visited before.
       // If a child does not have all of its ancestors visited, when those
       // ancestors will be visited, they will retry visiting this child.
-      element.visitChildren((dependent) {
-        if (dependent.container == this) {
-          // All the parents of a node must have been visited before a node is visited
-          var areAllAncestorsAlreadyVisited = true;
-          dependent.visitAncestors((e) {
-            if (e._container == this && !visitedNodes.contains(e)) {
-              areAllAncestorsAlreadyVisited = false;
-            }
-          });
+      element.visitChildren(
+        elementVisitor: (dependent) {
+          if (dependent.container == this) {
+            // All the parents of a node must have been visited before a node is visited
+            var areAllAncestorsAlreadyVisited = true;
+            dependent.visitAncestors((e) {
+              if (e._container == this && !visitedNodes.contains(e)) {
+                areAllAncestorsAlreadyVisited = false;
+              }
+            });
 
-          if (areAllAncestorsAlreadyVisited) queue.add(dependent);
-        }
-      });
+            if (areAllAncestorsAlreadyVisited) queue.add(dependent);
+          }
+        },
+        // We only care about Elements here, so let's ignore notifiers
+        notifierVisitor: (_) {},
+      );
     }
   }
 }
diff --git a/packages/riverpod/lib/src/framework/element.dart b/packages/riverpod/lib/src/framework/element.dart
new file mode 100644
index 0000000000..dfcc8707b8
--- /dev/null
+++ b/packages/riverpod/lib/src/framework/element.dart
@@ -0,0 +1,876 @@
+part of '../framework.dart';
+
+/// {@template riverpod.refreshable}
+/// An interface for provider expressions that can be passed to `ref.refresh`
+///
+/// This differentiates:
+///
+/// ```dart
+/// ref.watch(provider);
+/// ref.watch(provider.future);
+/// ```
+///
+/// from:
+///
+/// ```dart
+/// ref.watch(provider.select((value) => value));
+/// ```
+/// {@endtemplate}
+abstract class Refreshable<T> implements ProviderListenable<T> {
+  /// The provider that is being refreshed.
+  ProviderBase<Object?> get _origin;
+}
+
+/// {@macro riverpod.refreshable}
+abstract class AlwaysAliveRefreshable<T>
+    implements Refreshable<T>, AlwaysAliveProviderListenable<T> {}
+
+/// An internal class that handles the state of a provider.
+///
+/// Do not use.
+abstract class ProviderElementBase<State> implements Ref<State>, Node {
+  /// Do not use.
+  ProviderElementBase(this._provider);
+
+  static ProviderElementBase? _debugCurrentlyBuildingElement;
+
+  var _debugSkipNotifyListenersAsserts = false;
+
+  /// The provider associated with this [ProviderElementBase], before applying overrides.
+  // Not typed as <State> because of https://github.com/rrousselGit/river_pod/issues/1100
+  ProviderBase<Object?> get origin => _origin;
+  late ProviderBase<Object?> _origin;
+
+  /// The provider associated with this [ProviderElementBase], after applying overrides.
+  ProviderBase<State> get provider => _provider;
+  ProviderBase<State> _provider;
+
+  /// The [ProviderContainer] that owns this [ProviderElementBase].
+  @override
+  ProviderContainer get container => _container;
+  late ProviderContainer _container;
+
+  /// Whether this [ProviderElementBase] is currently listened to or not.
+  ///
+  /// This maps to listeners added with [listen].
+  /// See also [mayNeedDispose], called when [hasListeners] may have changed.
+  bool get hasListeners =>
+      _externalDependents.isNotEmpty ||
+      _subscribers.isNotEmpty ||
+      _providerDependents.isNotEmpty;
+
+  // TODO(rrousselGit) refactor to match ChangeNotifier
+  /// The list of [ProviderSubscription]s that are linked with this element,
+  /// which aren't coming from another provider.
+  ///
+  /// This is typically Flutter widgets or manual calls to [ProviderContainer.listen]
+  /// with this provider as target.
+  final _externalDependents = <_ExternalProviderSubscription<State>>[];
+
+  /// The [ProviderSubscription]s associated to the providers that this
+  /// [ProviderElementBase] listens to.
+  ///
+  /// This list is typically updated when this provider calls [listen] on
+  /// another provider.
+  final _listenedProviderSubscriptions = <_ProviderListener>[];
+
+  /// The element of the providers that depends on this provider.
+  final _providerDependents = <ProviderElementBase>[];
+
+  /// The subscriptions associated to other providers listening to this provider.
+  ///
+  /// Storing [_ProviderListener] instead of the raw [ProviderElementBase] as
+  /// a provider can listen multiple times to another provider with different listeners.
+  final _subscribers = <_ProviderListener>[];
+
+  var _dependencies = HashMap<ProviderElementBase, Object>();
+  HashMap<ProviderElementBase, Object>? _previousDependencies;
+  List<void Function()>? _onDisposeListeners;
+  List<void Function()>? _onResumeListeners;
+  List<void Function()>? _onCancelListeners;
+  List<void Function()>? _onAddListeners;
+  List<void Function()>? _onRemoveListeners;
+  List<void Function(State?, State)>? _onChangeSelfListeners;
+  List<void Function(Object, StackTrace)>? _onErrorSelfListeners;
+
+  bool _mustRecomputeState = false;
+  bool _dependencyMayHaveChanged = false;
+  bool _debugDidChangeDependency = false;
+  var _didCancelOnce = false;
+
+  bool _mounted = false;
+
+  /// Whether the element was disposed or not
+  @visibleForTesting
+  bool get mounted => _mounted;
+
+  /// Whether the assert that prevents [requireState] from returning
+  /// if the state was not set before is enabled.
+  @visibleForOverriding
+  bool get debugAssertDidSetStateEnabled => true;
+
+  bool _debugDidSetState = false;
+  bool _didBuild = false;
+
+  /* STATE */
+  Result<State>? _state;
+
+  /// Update the exposed value of a provider and notify its listeners.
+  ///
+  /// Listeners will only be notified if [ProviderBase.updateShouldNotify]
+  /// returns true.
+  ///
+  /// This API is not meant for public consumption. Instead if a [Ref] needs
+  /// to expose a way to update the state, the practice is to expose a getter/setter.
+  @protected
+  void setState(State newState) {
+    assert(() {
+      _debugDidSetState = true;
+      return true;
+    }(), '');
+    final previousResult = getState();
+
+    Result<State> newResult;
+    if (newState is AsyncValue && previousResult != null) {
+      final previousState = previousResult.requireState;
+
+      newResult = Result<State>.data(
+        newState.copyWithPrevious(previousState as AsyncValue) as State,
+      );
+    } else {
+      newResult = Result.data(newState);
+    }
+
+    final result = _state = newResult;
+
+    if (_didBuild) {
+      _notifyListeners(result, previousResult);
+    }
+  }
+
+  /// Obtains the current state, of null if the provider has yet to initialize.
+  ///
+  /// The returned object will contain error information, if any.
+  /// This function does not cause the provider to rebuild if it someohow was
+  /// outdated.
+  ///
+  /// This is not meant for public consumption. Instead, public API should use
+  /// [readSelf].
+  @protected
+  @visibleForTesting
+  Result<State>? getState() => _state;
+
+  /// Read the current value of a provider and:
+  ///
+  /// - if in error state, rethrow the error
+  /// - if the provider is not initialized, gracefully handle the error.
+  ///
+  /// This is not meant for public consumption. Instead, public API should use
+  /// [readSelf].
+  @protected
+  State get requireState {
+    assert(() {
+      if (debugAssertDidSetStateEnabled && !_debugDidSetState) {
+        throw StateError(
+          'Tried to read the state of an uninitialized provider',
+        );
+      }
+      return true;
+    }(), '');
+
+    final state = getState();
+    if (state == null) {
+      throw StateError('Tried to read the state of an uninitialized provider');
+    }
+
+    return state.when(
+      error: throwErrorWithCombinedStackTrace,
+      data: (data) => data,
+    );
+  }
+
+  /* /STATE */
+
+  /// Called the first time a provider is obtained.
+  @protected
+  @mustCallSuper
+  void mount() {
+    _mounted = true;
+    assert(() {
+      RiverpodBinding.debugInstance
+          .providerListChangedFor(containerId: container._debugId);
+
+      return true;
+    }(), '');
+    buildState();
+
+    _state!.map(
+      data: (newState) {
+        final onChangeSelfListeners = _onChangeSelfListeners;
+        if (onChangeSelfListeners != null) {
+          for (var i = 0; i < onChangeSelfListeners.length; i++) {
+            Zone.current.runBinaryGuarded(
+              onChangeSelfListeners[i],
+              null,
+              newState.state,
+            );
+          }
+        }
+      },
+      error: (newState) {
+        final onErrorSelfListeners = _onErrorSelfListeners;
+        if (onErrorSelfListeners != null) {
+          for (var i = 0; i < onErrorSelfListeners.length; i++) {
+            Zone.current.runBinaryGuarded(
+              onErrorSelfListeners[i],
+              newState.error,
+              newState.stackTrace,
+            );
+          }
+        }
+      },
+    );
+  }
+
+  // ignore: use_setters_to_change_properties
+  /// Called when the override of a provider changes.
+  ///
+  /// See also:
+  /// - `overrideWithValue`, which relies on [update] to handle
+  ///   the scenario where the value changed.
+  @protected
+  @mustCallSuper
+  // ignore: use_setters_to_change_properties
+  void update(ProviderBase<State> newProvider) {
+    _provider = newProvider;
+  }
+
+  @override
+  void invalidate(ProviderOrFamily provider) {
+    _container.invalidate(provider);
+  }
+
+  @override
+  void invalidateSelf() {
+    if (_mustRecomputeState) return;
+
+    _mustRecomputeState = true;
+    runOnDispose();
+    _container._scheduler.scheduleProviderRefresh(this);
+
+    // We don't call this._markDependencyMayHaveChanged here because we voluntarily
+    // do not want to set the _dependencyMayHaveChanged flag to true.
+    // Since the dependency is known to have changed, there is no reason to try
+    // and "flush" it, as it will already get rebuilt.
+    visitChildren(
+      elementVisitor: (element) => element._markDependencyMayHaveChanged(),
+      notifierVisitor: (notifier) => notifier.notifyDependencyMayHaveChanged(),
+    );
+  }
+
+  /// A utility for re-initializing a provider when needed.
+  ///
+  /// Calling [flush] will only re-initialize the provider if it needs to rerun.
+  /// This can involve:
+  /// - a previous call to [invalidateSelf]
+  /// - a dependency of the provider has changed (such as when using [watch]).
+  ///
+  /// This is not meant for public consumption. Public API should hide
+  /// [flush] from users, such that they don't need to care about invocing this function.
+  void flush() {
+    _maybeRebuildDependencies();
+    if (_mustRecomputeState) {
+      _mustRecomputeState = false;
+      _performBuild();
+    }
+  }
+
+  /// Iterates over the dependencies of this provider, calling [flush] on them too.
+  ///
+  /// This work is only performed if a dependency has notified that it might
+  /// need to be re-executed.
+  void _maybeRebuildDependencies() {
+    if (!_dependencyMayHaveChanged) return;
+
+    _dependencyMayHaveChanged = false;
+
+    visitAncestors(
+      (element) {
+        element.flush();
+      },
+    );
+  }
+
+  /// Initialize a provider and track dependencies used during the initialization.
+  ///
+  /// After a provider is initialized, this function takes care of unsubscribing
+  /// to dependencies that are no-longer used.
+  void _performBuild() {
+    _previousDependencies = _dependencies;
+    _dependencies = HashMap();
+
+    final previousStateResult = _state;
+
+    assert(() {
+      _debugDidSetState = false;
+      return true;
+    }(), '');
+    buildState();
+
+    if (!identical(_state, previousStateResult)) {
+      assert(() {
+        // Asserts would otherwise prevent a provider rebuild from updating
+        // other providers
+        _debugSkipNotifyListenersAsserts = true;
+        return true;
+      }(), '');
+      _notifyListeners(_state!, previousStateResult);
+      assert(() {
+        _debugSkipNotifyListenersAsserts = false;
+        return true;
+      }(), '');
+    }
+
+    // Unsubscribe to everything that a provider no longer depends on.
+    for (final sub in _previousDependencies!.entries) {
+      sub.key
+        .._providerDependents.remove(this)
+        .._onRemoveListener();
+    }
+    _previousDependencies = null;
+  }
+
+  /// Initialize a provider.
+  ///
+  /// This function **must** call [setState] or throw (or both).
+  ///
+  /// Exceptions within this function will be caught and set the provider in error
+  /// state. Then, reading this provider will rethrow the thrown exception.
+  @visibleForOverriding
+  @protected
+  void create();
+
+  /// Invokes [create] and handles errors.
+  @pragma('vm:notify-debugger-on-exception')
+  void buildState() {
+    ProviderElementBase? debugPreviouslyBuildingElement;
+    assert(() {
+      _debugDidChangeDependency = false;
+      debugPreviouslyBuildingElement = _debugCurrentlyBuildingElement;
+      _debugCurrentlyBuildingElement = this;
+      return true;
+    }(), '');
+    _didBuild = false;
+    try {
+      // TODO move outside this function?
+      _mounted = true;
+      create();
+    } catch (err, stack) {
+      assert(() {
+        _debugDidSetState = true;
+        return true;
+      }(), '');
+      _state = Result.error(err, stack);
+    } finally {
+      _didBuild = true;
+      assert(() {
+        _debugCurrentlyBuildingElement = debugPreviouslyBuildingElement;
+        return true;
+      }(), '');
+
+      assert(
+        getState() != null,
+        'Bad state, the provider did not initialize. Did "create" forget to set the state?',
+      );
+    }
+  }
+
+  void _notifyListeners(
+    Result<State> newState,
+    Result<State>? previousStateResult,
+  ) {
+    assert(() {
+      if (_debugSkipNotifyListenersAsserts) return true;
+
+      assert(
+          _debugCurrentlyBuildingElement == null ||
+              _debugCurrentlyBuildingElement == this,
+          '''
+Providers are not allowed to modify other providers during their initialization.
+
+The provider ${_debugCurrentlyBuildingElement!.origin} modified $origin while building.
+''');
+
+      container.debugCanModifyProviders?.call();
+      return true;
+    }(), '');
+
+    final previousState = previousStateResult?.stateOrNull;
+
+    // listenSelf listeners do not respect updateShouldNotify
+    newState.map(
+      data: (newState) {
+        final onChangeSelfListeners = _onChangeSelfListeners;
+        if (onChangeSelfListeners != null) {
+          for (var i = 0; i < onChangeSelfListeners.length; i++) {
+            Zone.current.runBinaryGuarded(
+              onChangeSelfListeners[i],
+              previousState,
+              newState.state,
+            );
+          }
+        }
+      },
+      error: (newState) {
+        final onErrorSelfListeners = _onErrorSelfListeners;
+        if (onErrorSelfListeners != null) {
+          for (var i = 0; i < onErrorSelfListeners.length; i++) {
+            Zone.current.runBinaryGuarded(
+              onErrorSelfListeners[i],
+              newState.error,
+              newState.stackTrace,
+            );
+          }
+        }
+      },
+    );
+
+    if (previousStateResult != null &&
+        previousStateResult.hasState &&
+        newState.hasState &&
+        !provider.updateShouldNotify(
+          previousState as State,
+          newState.requireState,
+        )) {
+      return;
+    }
+
+    final listeners = _externalDependents.toList(growable: false);
+    final subscribers = _subscribers.toList(growable: false);
+    newState.map(
+      data: (newState) {
+        for (var i = 0; i < listeners.length; i++) {
+          Zone.current.runBinaryGuarded(
+            listeners[i]._listener,
+            previousState,
+            newState.state,
+          );
+        }
+        for (var i = 0; i < subscribers.length; i++) {
+          Zone.current.runBinaryGuarded(
+            subscribers[i].listener,
+            previousState,
+            newState.state,
+          );
+        }
+      },
+      error: (newState) {
+        for (var i = 0; i < listeners.length; i++) {
+          Zone.current.runBinaryGuarded(
+            listeners[i].onError,
+            newState.error,
+            newState.stackTrace,
+          );
+        }
+        for (var i = 0; i < subscribers.length; i++) {
+          Zone.current.runBinaryGuarded(
+            subscribers[i].onError,
+            newState.error,
+            newState.stackTrace,
+          );
+        }
+      },
+    );
+
+    for (var i = 0; i < _providerDependents.length; i++) {
+      _providerDependents[i]._didChangeDependency();
+    }
+
+    for (final observer in _container._observers) {
+      runQuaternaryGuarded(
+        observer.didUpdateProvider,
+        provider,
+        previousState,
+        newState.stateOrNull,
+        _container,
+      );
+    }
+
+    for (final observer in _container._observers) {
+      newState.map(
+        data: (_) {},
+        error: (newState) {
+          runQuaternaryGuarded(
+            observer.providerDidFail,
+            provider,
+            newState.error,
+            newState.stackTrace,
+            _container,
+          );
+        },
+      );
+    }
+  }
+
+  void _didChangeDependency() {
+    assert(() {
+      _debugDidChangeDependency = true;
+      return true;
+    }(), '');
+    if (_mustRecomputeState) return;
+
+    // will notify children that their dependency may have changed
+    invalidateSelf();
+  }
+
+  void _markDependencyMayHaveChanged() {
+    if (_dependencyMayHaveChanged) return;
+
+    _dependencyMayHaveChanged = true;
+
+    visitChildren(
+      elementVisitor: (element) => element._markDependencyMayHaveChanged(),
+      notifierVisitor: (notifier) => notifier.notifyDependencyMayHaveChanged(),
+    );
+  }
+
+  bool _debugAssertCanDependOn(ProviderListenable listenable) {
+    assert(() {
+      if (listenable is! ProviderBase) return true;
+
+      assert(
+        listenable._origin != origin,
+        'A provider cannot depend on itself',
+      );
+
+      assert(
+        provider != origin ||
+            origin.dependencies == null ||
+            origin.dependencies!.contains(listenable.from) ||
+            origin.dependencies!.contains(listenable),
+        'The provider $origin tried to read $listenable, but it specified a '
+        "'dependendencies' list yet that list does not contain $listenable.\n\n"
+        "To fix, add $listenable to $origin's 'dependencies' parameter",
+      );
+
+      final queue = Queue<ProviderElementBase>.from(_providerDependents);
+
+      while (queue.isNotEmpty) {
+        final current = queue.removeFirst();
+        queue.addAll(current._providerDependents);
+
+        if (current.origin == listenable) {
+          throw CircularDependencyError._();
+        }
+      }
+
+      return true;
+    }(), '');
+    return true;
+  }
+
+  void _assertNotOutdated() {
+    assert(
+      _debugDidChangeDependency == false,
+      'Cannot use ref functions after the dependency of a provider changed but before the provider rebuilt',
+    );
+  }
+
+  @override
+  T refresh<T>(Refreshable<T> provider) {
+    _assertNotOutdated();
+    return _container.refresh(provider);
+  }
+
+  @override
+  T read<T>(ProviderListenable<T> provider) {
+    _assertNotOutdated();
+    assert(!_debugIsRunningSelector, 'Cannot call ref.read inside a selector');
+    assert(_debugAssertCanDependOn(provider), '');
+    return _container.read(provider);
+  }
+
+  @override
+  T watch<T>(ProviderListenable<T> listenable) {
+    _assertNotOutdated();
+    assert(!_debugIsRunningSelector, 'Cannot call ref.watch inside a selector');
+
+    if (listenable is! ProviderBase<T>) {
+      final sub = listen<T>(
+        listenable,
+        (prev, value) => _didChangeDependency(),
+        onError: (err, stack) => _didChangeDependency(),
+        onDependencyMayHaveChanged: _markDependencyMayHaveChanged,
+      );
+
+      return sub.read();
+    }
+
+    assert(_debugAssertCanDependOn(listenable), '');
+
+    final element = _container.readProviderElement(listenable);
+    _dependencies.putIfAbsent(element, () {
+      final previousSub = _previousDependencies?.remove(element);
+      if (previousSub != null) {
+        return previousSub;
+      }
+
+      assert(() {
+        // Flushing the provider before adding a new dependency
+        // as otherwise this could cause false positives with certain asserts.
+        // It's done only in debug mode since `readSelf` will flush the value
+        // again anyway, and the only value of this flush is to not break asserts.
+        element.flush();
+        return true;
+      }(), '');
+
+      element
+        .._onListen()
+        .._providerDependents.add(this);
+
+      return Object();
+    });
+
+    return element.readSelf();
+  }
+
+  @override
+  ProviderElementBase<T> readProviderElement<T>(ProviderBase<T> provider) {
+    return _container.readProviderElement(provider);
+  }
+
+  @override
+  ProviderSubscription<T> _listenElement<T>(
+    ProviderElementBase<T> element, {
+    required void Function(T? previous, T next) listener,
+    required void Function(Object error, StackTrace stackTrace) onError,
+  }) {
+    final sub = _ProviderListener<T>._(
+      listenedElement: element,
+      dependentElement: this,
+      listener: (prev, value) => listener(prev as T?, value as T),
+      onError: onError,
+    );
+
+    element._subscribers.add(sub);
+    _listenedProviderSubscriptions.add(sub);
+
+    return sub;
+  }
+
+  @override
+  ProviderSubscription<T> listen<T>(
+    ProviderListenable<T> listenable,
+    void Function(T? previous, T value) listener, {
+    void Function(Object error, StackTrace stackTrace)? onError,
+    bool fireImmediately = false,
+    // Not part of the public "Ref" API
+    void Function()? onDependencyMayHaveChanged,
+  }) {
+    _assertNotOutdated();
+    assert(!_debugIsRunningSelector, 'Cannot call ref.read inside a selector');
+    assert(_debugAssertCanDependOn(listenable), '');
+
+    return listenable.addListener(
+      this,
+      listener,
+      fireImmediately: fireImmediately,
+      onError: onError,
+      onDependencyMayHaveChanged: onDependencyMayHaveChanged,
+    );
+  }
+
+  @override
+  void listenSelf(
+    void Function(State? previous, State next) listener, {
+    void Function(Object error, StackTrace stackTrace)? onError,
+  }) {
+    // TODO do we want to expose a way to close the subscription?
+    // TODO do we want a fireImmdiately?
+
+    _onChangeSelfListeners ??= [];
+    _onChangeSelfListeners!.add(listener);
+
+    if (onError != null) {
+      _onErrorSelfListeners ??= [];
+      _onErrorSelfListeners!.add(onError);
+    }
+  }
+
+  /// Returns the currently exposed by a provider
+  ///
+  /// May throw if the provider threw when creating the exposed value.
+  State readSelf() {
+    flush();
+
+    return requireState;
+  }
+
+  /// Visit the [ProviderElement]s of providers that are listening to this element.
+  ///
+  /// A provider is considered as listening to this element if it either [watch]
+  /// or [listen] this element.
+  ///
+  /// This method does not guarantee that a dependency is visited only once.
+  /// If a provider both [watch] and [listen] an element, or if a provider
+  /// [listen] multiple times to an element, it may be visited multiple times.
+  void visitChildren({
+    required void Function(ProviderElementBase element) elementVisitor,
+    required void Function(ProxyElementValueNotifier element) notifierVisitor,
+  }) {
+    for (var i = 0; i < _providerDependents.length; i++) {
+      elementVisitor(_providerDependents[i]);
+    }
+
+    for (var i = 0; i < _subscribers.length; i++) {
+      elementVisitor(_subscribers[i].dependentElement);
+    }
+  }
+
+  /// Visit the [ProviderElementBase]s that this provider is listening to.
+  ///
+  /// A provider is considered as listening to this element if it either [watch]
+  /// or [listen] this element.
+  ///
+  /// This method does not guarantee that a provider is visited only once.
+  /// If this provider both [watch] and [listen] an element, or if it
+  /// [listen] multiple times to an element, that element may be visited multiple times.
+  void visitAncestors(void Function(ProviderElementBase element) visitor) {
+    _dependencies.keys.forEach(visitor);
+
+    for (var i = 0; i < _listenedProviderSubscriptions.length; i++) {
+      visitor(_listenedProviderSubscriptions[i].listenedElement);
+    }
+  }
+
+  /// Release the resources associated to this [ProviderElementBase].
+  ///
+  /// This will be invoked when:
+  /// - the provider is using `autoDispose` and it is no-longer used.
+  /// - the associated [ProviderContainer] is disposed
+  ///
+  /// On the other hand, this life-cycle will not be executed when a provider
+  /// rebuilds.
+  ///
+  /// As opposed to [runOnDispose], this life-cycle is executed only
+  /// for the lifetime of this element.
+  @protected
+  @mustCallSuper
+  void dispose() {
+    assert(() {
+      RiverpodBinding.debugInstance
+          .providerListChangedFor(containerId: container._debugId);
+      return true;
+    }(), '');
+
+    runOnDispose();
+
+    // TODO test invalidateSelf() then dispose() properly unlinks dependencies
+    // TODO test [listen] calls are cleared
+
+    for (final sub in _dependencies.entries) {
+      sub.key._providerDependents.remove(this);
+      sub.key._onRemoveListener();
+    }
+    _dependencies.clear();
+
+    _externalDependents.clear();
+  }
+
+  void _onListen() {
+    _onAddListeners?.forEach(runGuarded);
+    if (_didCancelOnce && !hasListeners) {
+      _onResumeListeners?.forEach(runGuarded);
+    }
+  }
+
+  void _onRemoveListener() {
+    _onRemoveListeners?.forEach(runGuarded);
+    if (!hasListeners) {
+      _didCancelOnce = true;
+      _onCancelListeners?.forEach(runGuarded);
+    }
+    mayNeedDispose();
+  }
+
+  /// Life-cycle for when a listener is removed.
+  ///
+  /// See also:
+  ///
+  /// - [AutoDisposeProviderElementMixin], which overrides this method to destroy the
+  ///   state of a provider when no longer used.
+  @protected
+  @visibleForOverriding
+  void mayNeedDispose() {}
+
+  @override
+  void onDispose(void Function() listener) {
+    _assertNotOutdated();
+    if (!_mounted) {
+      throw StateError('Cannot call onDispose after a provider was dispose');
+    }
+    _onDisposeListeners ??= [];
+    _onDisposeListeners!.add(listener);
+  }
+
+  /// Executes the [Ref.onDispose] listeners previously registered, then clear
+  /// the list of listeners.
+  @protected
+  @visibleForOverriding
+  void runOnDispose() {
+    if (!_mounted) return;
+    _mounted = false;
+
+    while (_listenedProviderSubscriptions.isNotEmpty) {
+      _listenedProviderSubscriptions.first.close();
+    }
+
+    _onDisposeListeners?.forEach(runGuarded);
+
+    for (final observer in _container._observers) {
+      runBinaryGuarded(
+        observer.didDisposeProvider,
+        _origin,
+        _container,
+      );
+    }
+
+    _onDisposeListeners = null;
+    _onCancelListeners = null;
+    _onResumeListeners = null;
+    _onAddListeners = null;
+    _onRemoveListeners = null;
+    _onChangeSelfListeners = null;
+    _onErrorSelfListeners = null;
+    _didCancelOnce = false;
+  }
+
+  @override
+  void onAddListener(void Function() cb) {
+    _onAddListeners ??= [];
+    _onAddListeners!.add(cb);
+  }
+
+  @override
+  void onRemoveListener(void Function() cb) {
+    _onRemoveListeners ??= [];
+    _onRemoveListeners!.add(cb);
+  }
+
+  @override
+  void onCancel(void Function() cb) {
+    _onCancelListeners ??= [];
+    _onCancelListeners!.add(cb);
+  }
+
+  @override
+  void onResume(void Function() cb) {
+    _onResumeListeners ??= [];
+    _onResumeListeners!.add(cb);
+  }
+
+  @override
+  String toString() {
+    return '$runtimeType(provider: $provider, origin: $origin)';
+  }
+}
diff --git a/packages/riverpod/lib/src/framework/family.dart b/packages/riverpod/lib/src/framework/family.dart
index 0947603d53..52431b212e 100644
--- a/packages/riverpod/lib/src/framework/family.dart
+++ b/packages/riverpod/lib/src/framework/family.dart
@@ -1,5 +1,11 @@
 part of '../framework.dart';
 
+/// A [Create] equivalent used by [Family].
+typedef FamilyCreate<T, R extends Ref, Arg> = T Function(
+  R ref,
+  Arg arg,
+);
+
 /// A base class for all families
 abstract class Family<State, Arg, FamilyProvider extends ProviderBase<State>>
     extends ProviderOrFamily implements FamilyOverride<Arg> {
@@ -7,8 +13,8 @@ abstract class Family<State, Arg, FamilyProvider extends ProviderBase<State>>
   Family({
     required this.name,
     required this.dependencies,
-    this.cacheTime,
-    this.disposeDelay,
+    required this.cacheTime,
+    required this.disposeDelay,
   });
 
   /// {@macro riverpod.cache_time}
@@ -39,11 +45,18 @@ abstract class Family<State, Arg, FamilyProvider extends ProviderBase<State>>
   ///
   /// That external value should be immutable and preferably override `==`/`hashCode`.
   /// See the documentation of [Provider.family] for more information.
-  FamilyProvider call(Arg argument) => create(argument);
+  FamilyProvider call(Arg argument);
 
-  /// Creates the provider for a given parameter.
-  @protected
-  FamilyProvider create(Arg argument);
+  /// Overrides the behavior of a family for a part of the application.
+  ///
+  /// {@macro riverpod.overrideWith}
+  Override overrideWithProvider(
+    FamilyProvider Function(Arg argument) override,
+  ) {
+    return _FamilyOverride<Arg>(this, (arg, setup) {
+      setup(origin: call(arg), override: override(arg));
+    });
+  }
 }
 
 /// Setup how a family is overridden
@@ -89,34 +102,103 @@ class _FamilyOverride<Arg> implements FamilyOverride<Arg> {
   }
 }
 
-/// An extension that adds [overrideWithProvider] to [Family].
-extension XFamily<State, Arg,
-        FamilyProvider extends AlwaysAliveProviderBase<State>>
-    on Family<State, Arg, FamilyProvider> {
-  /// Overrides the behavior of a family for a part of the application.
+/// A base implementation for [Family], used by the various providers to
+/// help them define a [Family].
+///
+/// This API is not meant for public consumption.
+class FamilyBase<RefT extends Ref<R>, R, Arg, Created,
+    ProviderT extends ProviderBase<R>> extends Family<R, Arg, ProviderT> {
+  /// A base implementation for [Family], used by the various providers to
+  /// help them define a [Family].
   ///
-  /// {@macro riverpod.overrideWith}
-  Override overrideWithProvider(
-    AlwaysAliveProviderBase<State> Function(Arg argument) override,
-  ) {
-    return _FamilyOverride<Arg>(this, (arg, setup) {
-      setup(origin: call(arg), override: override(arg));
-    });
-  }
+  /// This API is not meant for public consumption.
+  FamilyBase(
+    this._createFn, {
+    required ProviderT Function(
+      Create<Created, RefT> create, {
+      String? name,
+      Family from,
+      Object? argument,
+      List<ProviderOrFamily>? dependencies,
+    })
+        providerFactory,
+    required super.name,
+    required super.dependencies,
+  })  : _providerFactory = providerFactory,
+        super(
+          cacheTime: null,
+          disposeDelay: null,
+        );
+
+  final ProviderT Function(
+    Create<Created, RefT> create, {
+    String? name,
+    Family from,
+    Object? argument,
+    List<ProviderOrFamily>? dependencies,
+  }) _providerFactory;
+
+  final Created Function(RefT ref, Arg arg) _createFn;
+
+  @override
+  ProviderT call(Arg argument) => _providerFactory(
+        (ref) => _createFn(ref, argument),
+        name: name,
+        from: this,
+        argument: argument,
+        dependencies: dependencies,
+      );
 }
 
-/// An extension that adds [overrideWithProvider] to [Family].
-extension XAutoDisposeFamily<State, Arg,
-        FamilyProvider extends AutoDisposeProviderBase<State>>
-    on Family<State, Arg, FamilyProvider> {
-  /// Overrides the behavior of a family for a part of the application.
+/// A base implementation for [Family], used by the various providers to
+/// help them define a [Family].
+///
+/// This API is not meant for public consumption.
+
+class AutoDisposeFamilyBase<RefT extends Ref<R>, R, Arg, Created,
+    ProviderT extends ProviderBase<R>> extends Family<R, Arg, ProviderT> {
+  /// A base implementation for [Family], used by the various providers to
+  /// help them define a [Family].
   ///
-  /// {@macro riverpod.overrideWith}
-  Override overrideWithProvider(
-    AutoDisposeProviderBase<State> Function(Arg argument) override,
-  ) {
-    return _FamilyOverride<Arg>(this, (arg, setup) {
-      setup(origin: call(arg), override: override(arg));
-    });
-  }
+  /// This API is not meant for public consumption.
+  AutoDisposeFamilyBase(
+    this._createFn, {
+    required ProviderT Function(
+      Create<Created, RefT> create, {
+      String? name,
+      Family from,
+      Object? argument,
+      List<ProviderOrFamily>? dependencies,
+      Duration? cacheTime,
+      Duration? disposeDelay,
+    })
+        providerFactory,
+    required super.name,
+    required super.dependencies,
+    required super.cacheTime,
+    required super.disposeDelay,
+  }) : _providerFactory = providerFactory;
+
+  final ProviderT Function(
+    Create<Created, RefT> create, {
+    String? name,
+    Family from,
+    Object? argument,
+    List<ProviderOrFamily>? dependencies,
+    Duration? cacheTime,
+    Duration? disposeDelay,
+  }) _providerFactory;
+
+  final Created Function(RefT ref, Arg arg) _createFn;
+
+  @override
+  ProviderT call(Arg argument) => _providerFactory(
+        (ref) => _createFn(ref, argument),
+        name: name,
+        from: this,
+        argument: argument,
+        dependencies: dependencies,
+        cacheTime: cacheTime,
+        disposeDelay: disposeDelay,
+      );
 }
diff --git a/packages/riverpod/lib/src/framework/foundation.dart b/packages/riverpod/lib/src/framework/foundation.dart
index 3680bb0713..bdce7d3eed 100644
--- a/packages/riverpod/lib/src/framework/foundation.dart
+++ b/packages/riverpod/lib/src/framework/foundation.dart
@@ -72,10 +72,14 @@ mixin ProviderListenable<State> {
   ProviderSubscription<State> addListener(
     Node node,
     void Function(State? previous, State next) listener, {
-    void Function(Object error, StackTrace stackTrace)? onError,
-    bool fireImmediately = false,
+    required void Function(Object error, StackTrace stackTrace)? onError,
+    required void Function()? onDependencyMayHaveChanged,
+    required bool fireImmediately,
   });
 
+  /// Obtains the result of this provider expression without adding listener.
+  State read(Node node);
+
   /// Partially listen to a provider.
   ///
   /// Note: This method of listening to an object is currently only supported
diff --git a/packages/riverpod/lib/src/framework/listen.dart b/packages/riverpod/lib/src/framework/listen.dart
index 31b098120b..3f5cbfb509 100644
--- a/packages/riverpod/lib/src/framework/listen.dart
+++ b/packages/riverpod/lib/src/framework/listen.dart
@@ -8,7 +8,7 @@ void handleFireImmediately<State>(
   required void Function(Object error, StackTrace stackTrace) onError,
 }) {
   currentState.map(
-    data: (data) => _runBinaryGuarded(listener, null, data.state),
-    error: (error) => _runBinaryGuarded(onError, error.error, error.stackTrace),
+    data: (data) => runBinaryGuarded(listener, null, data.state),
+    error: (error) => runBinaryGuarded(onError, error.error, error.stackTrace),
   );
 }
diff --git a/packages/riverpod/lib/src/framework/provider_base.dart b/packages/riverpod/lib/src/framework/provider_base.dart
index dbd303837b..39c2c1149e 100644
--- a/packages/riverpod/lib/src/framework/provider_base.dart
+++ b/packages/riverpod/lib/src/framework/provider_base.dart
@@ -1,6 +1,3 @@
-// ignore_for_file: public_member_api_docs
-// TODO remove ignore_doc
-
 part of '../framework.dart';
 
 /// A callback used by providers to create the value exposed.
@@ -17,32 +14,49 @@ part of '../framework.dart';
 /// - [Provider], a provider that uses [Create] to expose an immutable value.
 typedef Create<T, R extends Ref> = T Function(R ref);
 
-/// A [Create] equivalent used by [Family].
-typedef FamilyCreate<T, R extends Ref, Arg> = T Function(
-  R ref,
-  Arg arg,
-);
-
-/// A function that reads the state of a provider.
-@Deprecated('Directly pass Ref to your providers instead')
-typedef Reader = T Function<T>(ProviderBase<T> provider);
-
 /// A base class for _all_ providers.
 @immutable
 abstract class ProviderBase<State> extends ProviderOrFamily
     with ProviderListenable<State>
-    implements ProviderOverride {
+    implements ProviderOverride, Refreshable<State> {
   /// A base class for _all_ providers.
   ProviderBase({
     required this.name,
     required this.from,
     required this.argument,
+    required this.cacheTime,
+    required this.disposeDelay,
   });
 
   @override
-  ProviderBase get _origin => originProvider;
+  ProviderBase get _origin => this;
+
   @override
-  ProviderBase get _override => originProvider;
+  ProviderBase get _override => this;
+
+  /// {@template riverpod.cache_time}
+  /// The minimum amount of time before an `autoDispose` provider can be
+  /// disposed if not listened after the last value change.
+  ///
+  /// If the provider rebuilds (such as when using `ref.watch` or `ref.refresh`)
+  /// or emits a new value, the timer will be refreshed.
+  ///
+  /// If null, use the nearest ancestor [ProviderContainer]'s [cacheTime].
+  /// If no ancestor is found, fallbacks to [Duration.zero].
+  /// {@endtemplate}
+  final Duration? cacheTime;
+
+  /// {@template riverpod.dispose_delay}
+  /// The amount of time before a provider is disposed after its last listener
+  /// is removed.
+  ///
+  /// If a new listener is added within that duration, the provider will not be
+  /// disposed.
+  ///
+  /// If null, use the nearest ancestor [ProviderContainer]'s [disposeDelay].
+  /// If no ancestor is found, fallbacks to [Duration.zero].
+  /// {@endtemplate}
+  final Duration? disposeDelay;
 
   /// {@template riverpod.name}
   /// A custom label for providers.
@@ -59,20 +73,13 @@ abstract class ProviderBase<State> extends ProviderOrFamily
   /// the variable that was used.
   final Object? argument;
 
-  /// The provider that will be refreshed when calling [ProviderContainer.refresh]
-  /// and that will be overridden when passed to `ProviderScope`.
-  ///
-  /// Defaults to `this`.
-  @visibleForOverriding
-  // ignore: avoid_returning_this
-  ProviderBase<Object?> get originProvider => this;
-
   @override
   ProviderSubscription<State> addListener(
     Node node,
     void Function(State? previous, State next) listener, {
-    void Function(Object error, StackTrace stackTrace)? onError,
-    bool fireImmediately = false,
+    required void Function(Object error, StackTrace stackTrace)? onError,
+    required void Function()? onDependencyMayHaveChanged,
+    required bool fireImmediately,
   }) {
     onError ??= Zone.current.handleUncaughtError;
 
@@ -89,16 +96,24 @@ abstract class ProviderBase<State> extends ProviderOrFamily
 
     element._onListen();
 
-    return node._createSubscription(
+    return node._listenElement(
       element,
       listener: listener,
       onError: onError,
     );
   }
 
-  /// Initializes the state of a provider
-  @visibleForOverriding
-  State create(covariant Ref ref);
+  @override
+  State read(Node node) {
+    final element = node.readProviderElement(this);
+
+    element.flush();
+
+    // In case `read` was called on a provider that has no listener
+    element.mayNeedDispose();
+
+    return element.requireState;
+  }
 
   /// Called when a provider is rebuilt. Used for providers to not notify their
   /// listeners if the exposed value did not change.
@@ -146,8 +161,9 @@ abstract class ProviderBase<State> extends ProviderOrFamily
 
 var _debugIsRunningSelector = false;
 
-class _ProviderSubscription<State> implements ProviderSubscription<State> {
-  _ProviderSubscription._(
+class _ExternalProviderSubscription<State>
+    implements ProviderSubscription<State> {
+  _ExternalProviderSubscription._(
     this._listenedElement,
     this._listener, {
     required this.onError,
@@ -161,7 +177,7 @@ class _ProviderSubscription<State> implements ProviderSubscription<State> {
   @override
   void close() {
     _closed = true;
-    _listenedElement._listeners.remove(this);
+    _listenedElement._externalDependents.remove(this);
     _listenedElement._onRemoveListener();
   }
 
@@ -193,7 +209,7 @@ class _ProviderListener<State> implements ProviderSubscription<State> {
 
   @override
   void close() {
-    dependentElement._subscriptions.remove(this);
+    dependentElement._listenedProviderSubscriptions.remove(this);
     listenedElement
       .._subscribers.remove(this)
       .._onRemoveListener();
@@ -203,783 +219,8 @@ class _ProviderListener<State> implements ProviderSubscription<State> {
   State read() => listenedElement.readSelf();
 }
 
-/// An internal class that handles the state of a provider.
-///
-/// Do not use.
-abstract class ProviderElementBase<State> implements Ref<State>, Node {
-  /// Do not use.
-  ProviderElementBase(this._provider);
-
-  static ProviderElementBase? _debugCurrentlyBuildingElement;
-
-  var _debugSkipNotifyListenersAsserts = false;
-
-  /// The provider associated with this [ProviderElementBase], before applying overrides.
-  // Not typed as <State> because of https://github.com/rrousselGit/river_pod/issues/1100
-  ProviderBase<Object?> get origin => _origin;
-  late ProviderBase<Object?> _origin;
-
-  /// The provider associated with this [ProviderElementBase], after applying overrides.
-  ProviderBase<State> get provider => _provider;
-  ProviderBase<State> _provider;
-
-  /// The [ProviderContainer] that owns this [ProviderElementBase].
-  @override
-  ProviderContainer get container => _container;
-  late ProviderContainer _container;
-
-  /// Whether this [ProviderElementBase] is currently listened to or not.
-  ///
-  /// This maps to listeners added with [listen].
-  /// See also [mayNeedDispose], called when [hasListeners] may have changed.
-  bool get hasListeners =>
-      _listeners.isNotEmpty ||
-      _subscribers.isNotEmpty ||
-      _dependents.isNotEmpty;
-
-  // TODO(rrousselGit) refactor to match ChangeNotifier
-  /// Accepts only _ProviderSubscription<State>, but not typed so that
-  /// _ProviderSubscription<void> is valid
-  final _listeners = <_ProviderSubscription<State>>[];
-  final _dependents = <ProviderElementBase>[];
-
-  /// The listeners that were added using [listen].
-  ///
-  /// This list allows us to traverse up in the provider graph.
-  final _subscriptions = <_ProviderListener>[];
-
-  /// The list of listeners added using [listen] from another provider.
-  ///
-  /// Storing ProviderListener instead of the provider Element as a provider
-  /// can listen another provider multiple times with different listeners.
-  final _subscribers = <_ProviderListener>[];
-
-  var _dependencies = HashMap<ProviderElementBase, Object>();
-  HashMap<ProviderElementBase, Object>? _previousDependencies;
-  List<void Function()>? _onDisposeListeners;
-  List<void Function()>? _onResumeListeners;
-  List<void Function()>? _onCancelListeners;
-  List<void Function()>? _onAddListeners;
-  List<void Function()>? _onRemoveListeners;
-  List<void Function(State?, State)>? _onChangeSelfListeners;
-  List<void Function(Object, StackTrace)>? _onErrorSelfListeners;
-
-  bool _mustRecomputeState = false;
-  bool _dependencyMayHaveChanged = false;
-  bool _debugDidChangeDependency = false;
-  var _didCancelOnce = false;
-
-  bool _mounted = false;
-
-  /// Whether the element was disposed or not
-  @visibleForTesting
-  bool get mounted => _mounted;
-
-  /// Whether the assert that prevents [requireState] from returning
-  /// if the state was not set before is enabled.
-  @visibleForOverriding
-  bool get debugAssertDidSetStateEnabled => true;
-
-  bool _debugDidSetState = false;
-  bool _didBuild = false;
-
-  /* STATE */
-  Result<State>? _state;
-
-  void setState(State newState) {
-    assert(() {
-      _debugDidSetState = true;
-      return true;
-    }(), '');
-    final previousResult = getState();
-
-    Result<State> newResult;
-    if (newState is AsyncValue && previousResult != null) {
-      final previousState = previousResult.requireState;
-
-      newResult = Result<State>.data(
-        newState.copyWithPrevious(previousState as AsyncValue) as State,
-      );
-    } else {
-      newResult = Result.data(newState);
-    }
-
-    final result = _state = newResult;
-
-    if (_didBuild) {
-      _notifyListeners(result, previousResult);
-    }
-  }
-
-  Result<State>? getState() => _state;
-
-  // TODO make protected
-  State get requireState {
-    assert(() {
-      if (debugAssertDidSetStateEnabled && !_debugDidSetState) {
-        throw StateError(
-          'Tried to read the state of an uninitialized provider',
-        );
-      }
-      return true;
-    }(), '');
-
-    final state = getState();
-    if (state == null) {
-      throw StateError('uninitialized');
-    }
-
-    return state.map(
-      error: (error) => throwErrorWithCombinedStackTrace(
-        error.error,
-        error.stackTrace,
-      ),
-      data: (data) => data.state,
-    );
-  }
-
-  /* /STATE */
-
-  /// Called the first time a provider is obtained.
-  @protected
-  @mustCallSuper
-  void mount() {
-    _mounted = true;
-    assert(() {
-      RiverpodBinding.debugInstance
-          .providerListChangedFor(containerId: container._debugId);
-
-      return true;
-    }(), '');
-    _buildState();
-
-    _state!.map(
-      data: (newState) {
-        final onChangeSelfListeners = _onChangeSelfListeners;
-        if (onChangeSelfListeners != null) {
-          for (var i = 0; i < onChangeSelfListeners.length; i++) {
-            Zone.current.runBinaryGuarded(
-              onChangeSelfListeners[i],
-              null,
-              newState.state,
-            );
-          }
-        }
-      },
-      error: (newState) {
-        final onErrorSelfListeners = _onErrorSelfListeners;
-        if (onErrorSelfListeners != null) {
-          for (var i = 0; i < onErrorSelfListeners.length; i++) {
-            Zone.current.runBinaryGuarded(
-              onErrorSelfListeners[i],
-              newState.error,
-              newState.stackTrace,
-            );
-          }
-        }
-      },
-    );
-  }
-
-  // ignore: use_setters_to_change_properties
-  /// Called when the override of a provider changes.
-  ///
-  /// See also:
-  /// - `overrideWithValue`, which relies on [update] to handle
-  ///   the scenario where the value changed.
-  @protected
-  @mustCallSuper
-  // ignore: use_setters_to_change_properties
-  void update(ProviderBase<State> newProvider) {
-    _provider = newProvider;
-  }
-
-  @override
-  void invalidate(ProviderOrFamily provider) {
-    _container.invalidate(provider);
-  }
-
-  @override
-  void invalidateSelf() {
-    if (_mustRecomputeState) return;
-
-    _mustRecomputeState = true;
-    _runOnDispose();
-    _container._scheduler.scheduleProviderRefresh(this);
-
-    // We don't call this._markDependencyMayHaveChanged here because we voluntarily
-    // do not want to set the _dependencyMayHaveChanged flag to true.
-    // Since the dependency is known to have changed, there is no reason to try
-    // and "flush" it, as it will already get rebuilt.
-    visitChildren((element) => element._markDependencyMayHaveChanged());
-  }
-
-  void flush() {
-    _maybeRebuildDependencies();
-    if (_mustRecomputeState) {
-      _mustRecomputeState = false;
-      _performBuild();
-    }
-  }
-
-  void _maybeRebuildDependencies() {
-    if (!_dependencyMayHaveChanged) {
-      return;
-    }
-    _dependencyMayHaveChanged = false;
-
-    visitAncestors((element) => element.flush());
-  }
-
-  void _performBuild() {
-    _previousDependencies = _dependencies;
-    _dependencies = HashMap();
-
-    final previousStateResult = _state;
-
-    assert(() {
-      _debugDidSetState = false;
-      return true;
-    }(), '');
-    _buildState();
-
-    if (!identical(_state, previousStateResult)) {
-      assert(() {
-        // Asserts would otherwise prevent a provider rebuild from updating
-        // other providers
-        _debugSkipNotifyListenersAsserts = true;
-        return true;
-      }(), '');
-      _notifyListeners(_state!, previousStateResult);
-      assert(() {
-        _debugSkipNotifyListenersAsserts = false;
-        return true;
-      }(), '');
-    }
-
-    // Unsubscribe to everything that a provider no longer depends on.
-    for (final sub in _previousDependencies!.entries) {
-      sub.key
-        .._dependents.remove(this)
-        .._onRemoveListener();
-    }
-    _previousDependencies = null;
-  }
-
-  @pragma('vm:notify-debugger-on-exception')
-  void _buildState() {
-    ProviderElementBase? debugPreviouslyBuildingElement;
-    assert(() {
-      _debugDidChangeDependency = false;
-      debugPreviouslyBuildingElement = _debugCurrentlyBuildingElement;
-      _debugCurrentlyBuildingElement = this;
-      return true;
-    }(), '');
-    _didBuild = false;
-    try {
-      // TODO move outside this function?
-      _mounted = true;
-      setState(_provider.create(this));
-    } catch (err, stack) {
-      assert(() {
-        _debugDidSetState = true;
-        return true;
-      }(), '');
-      _state = Result.error(err, stack);
-    } finally {
-      _didBuild = true;
-      assert(() {
-        _debugCurrentlyBuildingElement = debugPreviouslyBuildingElement;
-        return true;
-      }(), '');
-    }
-  }
-
-  void _notifyListeners(
-    Result<State> newState,
-    Result<State>? previousStateResult,
-  ) {
-    assert(() {
-      if (_debugSkipNotifyListenersAsserts) return true;
-
-      assert(
-          _debugCurrentlyBuildingElement == null ||
-              _debugCurrentlyBuildingElement == this,
-          '''
-Providers are not allowed to modify other providers during their initialization.
-
-The provider ${_debugCurrentlyBuildingElement!.origin} modified $origin while building.
-''');
-
-      container.debugCanModifyProviders?.call();
-      return true;
-    }(), '');
-
-    final previousState = previousStateResult?.stateOrNull;
-
-    // listenSelf listeners do not respect updateShouldNotify
-    newState.map(
-      data: (newState) {
-        final onChangeSelfListeners = _onChangeSelfListeners;
-        if (onChangeSelfListeners != null) {
-          for (var i = 0; i < onChangeSelfListeners.length; i++) {
-            Zone.current.runBinaryGuarded(
-              onChangeSelfListeners[i],
-              previousState,
-              newState.state,
-            );
-          }
-        }
-      },
-      error: (newState) {
-        final onErrorSelfListeners = _onErrorSelfListeners;
-        if (onErrorSelfListeners != null) {
-          for (var i = 0; i < onErrorSelfListeners.length; i++) {
-            Zone.current.runBinaryGuarded(
-              onErrorSelfListeners[i],
-              newState.error,
-              newState.stackTrace,
-            );
-          }
-        }
-      },
-    );
-
-    if (previousStateResult != null &&
-        previousStateResult.hasState &&
-        newState.hasState &&
-        !provider.updateShouldNotify(
-          previousState as State,
-          newState.requireState,
-        )) {
-      return;
-    }
-
-    final listeners = _listeners.toList(growable: false);
-    final subscribers = _subscribers.toList(growable: false);
-    newState.map(
-      data: (newState) {
-        for (var i = 0; i < listeners.length; i++) {
-          Zone.current.runBinaryGuarded(
-            listeners[i]._listener,
-            previousState,
-            newState.state,
-          );
-        }
-        for (var i = 0; i < subscribers.length; i++) {
-          Zone.current.runBinaryGuarded(
-            subscribers[i].listener,
-            previousState,
-            newState.state,
-          );
-        }
-      },
-      error: (newState) {
-        for (var i = 0; i < listeners.length; i++) {
-          Zone.current.runBinaryGuarded(
-            listeners[i].onError,
-            newState.error,
-            newState.stackTrace,
-          );
-        }
-        for (var i = 0; i < subscribers.length; i++) {
-          Zone.current.runBinaryGuarded(
-            subscribers[i].onError,
-            newState.error,
-            newState.stackTrace,
-          );
-        }
-      },
-    );
-
-    for (var i = 0; i < _dependents.length; i++) {
-      _dependents[i]._didChangeDependency();
-    }
-
-    for (final observer in _container._observers) {
-      _runQuaternaryGuarded(
-        observer.didUpdateProvider,
-        provider,
-        previousState,
-        newState.stateOrNull,
-        _container,
-      );
-    }
-
-    for (final observer in _container._observers) {
-      newState.map(
-        data: (_) {},
-        error: (newState) {
-          _runQuaternaryGuarded(
-            observer.providerDidFail,
-            provider,
-            newState.error,
-            newState.stackTrace,
-            _container,
-          );
-        },
-      );
-    }
-  }
-
-  void _didChangeDependency() {
-    assert(() {
-      _debugDidChangeDependency = true;
-      return true;
-    }(), '');
-    if (_mustRecomputeState) return;
-
-    // will notify children that their dependency may have changed
-    invalidateSelf();
-  }
-
-  void _markDependencyMayHaveChanged() {
-    if (_dependencyMayHaveChanged) return;
-
-    _dependencyMayHaveChanged = true;
-
-    visitChildren((element) => element._markDependencyMayHaveChanged());
-  }
-
-  bool _debugAssertCanDependOn(ProviderListenable listenable) {
-    assert(() {
-      if (listenable is! ProviderBase) return true;
-
-      assert(
-        listenable.originProvider != origin,
-        'A provider cannot depend on itself',
-      );
-
-      assert(
-        provider != origin ||
-            origin.dependencies == null ||
-            origin.dependencies!.contains(listenable.from) ||
-            origin.dependencies!.contains(listenable),
-        'The provider $origin tried to read $listenable, but it specified a '
-        "'dependendencies' list yet that list does not contain $listenable.\n\n"
-        "To fix, add $listenable to $origin's 'dependencies' parameter",
-      );
-
-      final queue = Queue<ProviderElementBase>.from(_dependents);
-
-      while (queue.isNotEmpty) {
-        final current = queue.removeFirst();
-        queue.addAll(current._dependents);
-
-        if (current.origin == listenable) {
-          throw CircularDependencyError._();
-        }
-      }
-
-      return true;
-    }(), '');
-    return true;
-  }
-
-  void _assertNotOutdated() {
-    assert(
-      _debugDidChangeDependency == false,
-      'Cannot use ref functions after the dependency of a provider changed but before the provider rebuilt',
-    );
-  }
-
-  @override
-  T refresh<T>(ProviderBase<T> provider) {
-    _assertNotOutdated();
-    return _container.refresh(provider);
-  }
-
-  @override
-  T read<T>(ProviderBase<T> provider) {
-    _assertNotOutdated();
-    assert(!_debugIsRunningSelector, 'Cannot call ref.read inside a selector');
-    assert(_debugAssertCanDependOn(provider), '');
-    return _container.read(provider);
-  }
-
-  @override
-  T watch<T>(ProviderListenable<T> listenable) {
-    _assertNotOutdated();
-    assert(!_debugIsRunningSelector, 'Cannot call ref.watch inside a selector');
-
-    if (listenable is! ProviderBase<T>) {
-      var initialized = false;
-      late Result<T> firstValue;
-
-      listen<T>(
-        listenable,
-        (prev, value) {
-          if (initialized) {
-            _didChangeDependency();
-          } else {
-            firstValue = Result.data(value);
-            initialized = true;
-          }
-        },
-        onError: (err, stack) {
-          if (initialized) {
-            _didChangeDependency();
-          } else {
-            initialized = true;
-            firstValue = Result.error(err, stack);
-          }
-        },
-        fireImmediately: true,
-      );
-
-      return firstValue.requireState;
-    }
-
-    assert(_debugAssertCanDependOn(listenable), '');
-
-    final element = _container.readProviderElement(listenable);
-    _dependencies.putIfAbsent(element, () {
-      final previousSub = _previousDependencies?.remove(element);
-      if (previousSub != null) {
-        return previousSub;
-      }
-
-      assert(() {
-        // Flushing the provider before adding a new dependency
-        // as otherwise this could cause false positives with certain asserts.
-        // It's done only in debug mode since `readSelf` will flush the value
-        // again anyway, and the only value of this flush is to not break asserts.
-        element.flush();
-        return true;
-      }(), '');
-
-      element
-        .._onListen()
-        .._dependents.add(this);
-
-      return Object();
-    });
-
-    return element.readSelf();
-  }
-
-  @override
-  ProviderElementBase<T> readProviderElement<T>(ProviderBase<T> provider) {
-    return _container.readProviderElement(provider);
-  }
-
-  @override
-  ProviderSubscription<T> _createSubscription<T>(
-    ProviderElementBase<T> element, {
-    required void Function(T? previous, T next) listener,
-    required void Function(Object error, StackTrace stackTrace) onError,
-  }) {
-    final sub = _ProviderListener<T>._(
-      listenedElement: element,
-      dependentElement: this,
-      listener: (prev, value) => listener(prev as T?, value as T),
-      onError: onError,
-    );
-
-    element._subscribers.add(sub);
-    _subscriptions.add(sub);
-
-    return sub;
-  }
-
-  @override
-  ProviderSubscription<T> listen<T>(
-    ProviderListenable<T> listenable,
-    void Function(T? previous, T value) listener, {
-    void Function(Object error, StackTrace stackTrace)? onError,
-    bool fireImmediately = false,
-  }) {
-    _assertNotOutdated();
-    assert(!_debugIsRunningSelector, 'Cannot call ref.read inside a selector');
-    assert(_debugAssertCanDependOn(listenable), '');
-
-    return listenable.addListener(
-      this,
-      listener,
-      fireImmediately: fireImmediately,
-      onError: onError,
-    );
-  }
-
-  @override
-  void listenSelf(
-    void Function(State? previous, State next) listener, {
-    void Function(Object error, StackTrace stackTrace)? onError,
-  }) {
-    // TODO do we want to expose a way to close the subscription?
-    // TODO do we want a fireImmdiately?
-
-    _onChangeSelfListeners ??= [];
-    _onChangeSelfListeners!.add(listener);
-
-    if (onError != null) {
-      _onErrorSelfListeners ??= [];
-      _onErrorSelfListeners!.add(onError);
-    }
-  }
-
-  /// Returns the currently exposed by a provider
-  ///
-  /// May throw if the provider threw when creating the exposed value.
-  State readSelf() {
-    flush();
-
-    return requireState;
-  }
-
-  /// Visit the [ProviderElement]s of providers that are listening to this element.
-  ///
-  /// A provider is considered as listening to this element if it either [watch]
-  /// or [listen] this element.
-  ///
-  /// This method does not guarantee that a dependency is visited only once.
-  /// If a provider both [watch] and [listen] an element, or if a provider
-  /// [listen] multiple times to an element, it may be visited multiple times.
-  void visitChildren(void Function(ProviderElementBase element) visitor) {
-    for (var i = 0; i < _dependents.length; i++) {
-      visitor(_dependents[i]);
-    }
-
-    for (var i = 0; i < _subscribers.length; i++) {
-      visitor(_subscribers[i].dependentElement);
-    }
-  }
-
-  /// Visit the [ProviderElementBase]s that this provider is listening to.
-  ///
-  /// A provider is considered as listening to this element if it either [watch]
-  /// or [listen] this element.
-  ///
-  /// This method does not guarantee that a provider is visited only once.
-  /// If this provider both [watch] and [listen] an element, or if it
-  /// [listen] multiple times to an element, that element may be visited multiple times.
-  void visitAncestors(void Function(ProviderElementBase element) visitor) {
-    _dependencies.keys.forEach(visitor);
-
-    for (var i = 0; i < _subscriptions.length; i++) {
-      visitor(_subscriptions[i].listenedElement);
-    }
-  }
-
-  /// Called on [ProviderContainer.dispose].
-  @protected
-  @mustCallSuper
-  void dispose() {
-    assert(() {
-      RiverpodBinding.debugInstance
-          .providerListChangedFor(containerId: container._debugId);
-      return true;
-    }(), '');
-
-    _runOnDispose();
-
-    // TODO test invalidateSelf() then dispose() properly unlinks dependencies
-    // TODO test [listen] calls are cleared
-
-    for (final sub in _dependencies.entries) {
-      sub.key._dependents.remove(this);
-      sub.key._onRemoveListener();
-    }
-    _dependencies.clear();
-
-    _listeners.clear();
-  }
-
-  void _onListen() {
-    _onAddListeners?.forEach(_runGuarded);
-    if (_didCancelOnce && !hasListeners) {
-      _onResumeListeners?.forEach(_runGuarded);
-    }
-  }
-
-  void _onRemoveListener() {
-    _onRemoveListeners?.forEach(_runGuarded);
-    if (!hasListeners) {
-      _didCancelOnce = true;
-      _onCancelListeners?.forEach(_runGuarded);
-    }
-    mayNeedDispose();
-  }
-
-  /// Life-cycle for when a listener is removed.
-  ///
-  /// See also:
-  ///
-  /// - [AutoDisposeProviderElementBase], which overrides this method to destroy the
-  ///   state of a provider when no longer used.
-  @protected
-  @visibleForOverriding
-  void mayNeedDispose() {}
-
-  @override
-  void onDispose(void Function() listener) {
-    _assertNotOutdated();
-    if (!_mounted) {
-      throw StateError('Cannot call onDispose after a provider was dispose');
-    }
-    _onDisposeListeners ??= [];
-    _onDisposeListeners!.add(listener);
-  }
-
-  @protected
-  void _runOnDispose() {
-    if (!_mounted) return;
-    _mounted = false;
-
-    while (_subscriptions.isNotEmpty) {
-      _subscriptions.first.close();
-    }
-
-    _onDisposeListeners?.forEach(_runGuarded);
-
-    for (final observer in _container._observers) {
-      _runBinaryGuarded(
-        observer.didDisposeProvider,
-        _origin,
-        _container,
-      );
-    }
-
-    _onDisposeListeners = null;
-    _onCancelListeners = null;
-    _onResumeListeners = null;
-    _onAddListeners = null;
-    _onRemoveListeners = null;
-    _onChangeSelfListeners = null;
-    _onErrorSelfListeners = null;
-    _didCancelOnce = false;
-  }
-
-  @override
-  void onAddListener(void Function() cb) {
-    _onAddListeners ??= [];
-    _onAddListeners!.add(cb);
-  }
-
-  @override
-  void onRemoveListener(void Function() cb) {
-    _onRemoveListeners ??= [];
-    _onRemoveListeners!.add(cb);
-  }
-
-  @override
-  void onCancel(void Function() cb) {
-    _onCancelListeners ??= [];
-    _onCancelListeners!.add(cb);
-  }
-
-  @override
-  void onResume(void Function() cb) {
-    _onResumeListeners ??= [];
-    _onResumeListeners!.add(cb);
-  }
-
-  @override
-  String toString() {
-    return '$runtimeType(provider: $provider, origin: $origin)';
-  }
-}
-
+/// A mixin to add [overrideWithValue] capability to a provider.
+// TODO merge with Provider directy
 mixin OverrideWithValueMixin<State> on ProviderBase<State> {
   /// {@template riverpod.overrridewithvalue}
   /// Overrides a provider with a value, ejecting the default behaviour.
@@ -1021,10 +262,9 @@ mixin OverrideWithValueMixin<State> on ProviderBase<State> {
   }
 }
 
-mixin OverrideWithProviderMixin<State,
-    ProviderType extends ProviderBase<Object?>> {
-  ProviderBase<State> get originProvider;
-
+/// A mixin to add [overrideWithProvider] capability to providers.
+extension OverrideWithProviderExtension<State,
+    ProviderType extends ProviderBase<State>> on ProviderType {
   /// {@template riverpod.overridewithprovider}
   /// Overrides a provider with a value, ejecting the default behaviour.
   ///
@@ -1061,111 +301,12 @@ mixin OverrideWithProviderMixin<State,
   /// );
   /// ```
   /// {@endtemplate}
-  Override overrideWithProvider(ProviderType value) {
+  Override overrideWithProvider(ProviderType override) {
     assert(
-      value.originProvider.dependencies == null,
+      override.dependencies == null,
       'When using overrideWithProvider, the override cannot specify `dependencies`.',
     );
 
-    return ProviderOverride(
-      origin: originProvider,
-      override: value.originProvider,
-    );
-  }
-}
-
-@immutable
-abstract class Result<State> {
-  // coverage:ignore-start
-  factory Result.data(State state) = ResultData;
-  // coverage:ignore-end
-
-  // coverage:ignore-start
-  factory Result.error(Object error, StackTrace stackTrace) = ResultError;
-  // coverage:ignore-end
-
-  static Result<State> guard<State>(State Function() cb) {
-    try {
-      return Result.data(cb());
-    } catch (err, stack) {
-      return Result.error(err, stack);
-    }
-  }
-
-  bool get hasState;
-
-  State? get stateOrNull;
-  State get requireState;
-
-  R map<R>({
-    required R Function(ResultData<State> data) data,
-    required R Function(ResultError<State>) error,
-  });
-}
-
-class ResultData<State> implements Result<State> {
-  ResultData(this.state);
-
-  final State state;
-
-  @override
-  bool get hasState => true;
-
-  @override
-  State? get stateOrNull => state;
-
-  @override
-  State get requireState => state;
-
-  @override
-  R map<R>({
-    required R Function(ResultData<State> data) data,
-    required R Function(ResultError<State>) error,
-  }) {
-    return data(this);
+    return ProviderOverride(origin: this, override: override);
   }
-
-  @override
-  bool operator ==(Object? other) =>
-      other is ResultData<State> &&
-      other.runtimeType == runtimeType &&
-      other.state == state;
-
-  @override
-  int get hashCode => Object.hash(runtimeType, state);
-}
-
-class ResultError<State> implements Result<State> {
-  ResultError(this.error, this.stackTrace);
-
-  final Object error;
-  final StackTrace stackTrace;
-
-  @override
-  bool get hasState => false;
-
-  @override
-  State? get stateOrNull => null;
-
-  @override
-  // ignore: only_throw_errors
-  State get requireState => throw error;
-
-  @override
-  R map<R>({
-    required R Function(ResultData<State> data) data,
-    required R Function(ResultError<State>) error,
-  }) {
-    return error(this);
-  }
-
-  @override
-  bool operator ==(Object? other) =>
-      other is ResultError<State> &&
-      other.runtimeType == runtimeType &&
-      other.stackTrace == stackTrace &&
-      other.error == error;
-
-  @override
-  int get hashCode => Object.hash(runtimeType, error, stackTrace);
 }
diff --git a/packages/riverpod/lib/src/framework/proxy_provider_listenable.dart b/packages/riverpod/lib/src/framework/proxy_provider_listenable.dart
new file mode 100644
index 0000000000..5ecee13653
--- /dev/null
+++ b/packages/riverpod/lib/src/framework/proxy_provider_listenable.dart
@@ -0,0 +1,124 @@
+part of '../framework.dart';
+
+class _ProxySubscription<T> extends ProviderSubscription<T> {
+  _ProxySubscription(
+    this._removeListeners,
+    this._read, {
+    required this.innerSubscription,
+  });
+
+  final ProviderSubscription innerSubscription;
+  final RemoveListener _removeListeners;
+  final T Function() _read;
+
+  @override
+  void close() {
+    innerSubscription.close();
+    _removeListeners();
+  }
+
+  @override
+  T read() => _read();
+}
+
+/// An internal utility for reading alternate values of a provider.
+///
+/// For example, this is used by [FutureProvider] to differentiate:
+///
+/// ```dart
+/// ref.watch(futureProvider);
+/// ```
+///
+/// from:
+///
+/// ```dart
+/// ref.watch(futureProvider.future);
+/// ```
+///
+/// This API is not meant for public consumption.
+class ProviderElementProxy<Input, Output>
+    with ProviderListenable<Output>, AlwaysAliveProviderListenable<Output>
+    implements AlwaysAliveRefreshable<Output> {
+  /// An internal utility for reading alternate values of a provider.
+  ///
+  /// For example, this is used by [FutureProvider] to differentiate:
+  ///
+  /// ```dart
+  /// ref.watch(futureProvider);
+  /// ```
+  ///
+  /// from:
+  ///
+  /// ```dart
+  /// ref.watch(futureProvider.future);
+  /// ```
+  ///
+  /// This API is not meant for public consumption.
+  const ProviderElementProxy(this._origin, this._lense);
+
+  @override
+  final ProviderBase<Input> _origin;
+  final ProxyElementValueNotifier<Output> Function(
+    ProviderElementBase<Input> element,
+  ) _lense;
+
+  @override
+  ProviderSubscription<Output> addListener(
+    Node node,
+    void Function(Output? previous, Output next) listener, {
+    required void Function(Object error, StackTrace stackTrace)? onError,
+    required void Function()? onDependencyMayHaveChanged,
+    required bool fireImmediately,
+  }) {
+    final element = node.readProviderElement(_origin);
+
+    // TODO does this need a "flush"?
+
+    final notifier = _lense(element);
+    if (fireImmediately) {
+      notifier.result?.when(
+        data: (data) {
+          runBinaryGuarded(listener, null, data);
+        },
+        error: (err, stack) {
+          if (onError != null) {
+            runBinaryGuarded(onError, err, stack);
+          }
+        },
+      );
+    }
+
+    final removeListener = notifier.addListener(
+      listener,
+      onError: onError,
+      onDependencyMayHaveChanged: onDependencyMayHaveChanged,
+    );
+
+    return _ProxySubscription(
+      removeListener,
+      () => read(node),
+      // While we don't care about changes to the element, calling _listenElement
+      // is necessary to tell the listened element that it is being listened.
+      innerSubscription: node._listenElement<Input>(
+        element,
+        listener: (prev, next) {},
+        onError: (err, stack) {},
+      ),
+    );
+  }
+
+  @override
+  Output read(Node node) {
+    final element = node.readProviderElement(_origin);
+    element.flush();
+    element.mayNeedDispose();
+    return _lense(element).value;
+  }
+
+  @override
+  bool operator ==(Object other) =>
+      other is ProviderElementProxy<Input, Output> && other._origin == _origin;
+
+  @override
+  int get hashCode => _origin.hashCode;
+}
diff --git a/packages/riverpod/lib/src/framework/ref.dart b/packages/riverpod/lib/src/framework/ref.dart
index a8a3a2cbb0..8adf09226a 100644
--- a/packages/riverpod/lib/src/framework/ref.dart
+++ b/packages/riverpod/lib/src/framework/ref.dart
@@ -24,7 +24,7 @@ abstract class Ref<State extends Object?> {
   /// This method is useful for features like "pull to refresh" or "retry on error",
   /// to restart a specific provider.
   /// {@endtemplate}
-  T refresh<T>(ProviderBase<T> provider);
+  T refresh<T>(Refreshable<T> provider);
 
   /// {@template riverpod.invalidate}
   /// Invalidates the state of the provider, causing it to refresh.
@@ -157,7 +157,7 @@ abstract class Ref<State extends Object?> {
   ///
   /// If possible, avoid using [read] and prefer [watch], which is generally
   /// safer to use.
-  T read<T>(ProviderBase<T> provider);
+  T read<T>(ProviderListenable<T> provider);
 
   /// Obtains the state of a provider and causes the state to be re-evaluated
   /// when that provider emits a new value.
@@ -237,3 +237,48 @@ abstract class Ref<State extends Object?> {
     bool fireImmediately,
   });
 }
+
+/// A [Ref] for providers that are automatically destroyed when
+/// no longer used.
+///
+/// The difference with [Ref] is that it has an extra
+/// [keepAlive] function to help determine if the state can be destroyed
+///  or not.
+abstract class AutoDisposeRef<State> extends Ref<State> {
+  /// Whether to destroy the state of the provider when all listeners are removed or not.
+  ///
+  /// Can be changed at any time, in which case when setting it to `false`,
+  /// may destroy the provider state if it currently has no listeners.
+  ///
+  /// Defaults to `false`.
+  @Deprecated('use keepAlive() instead')
+  bool get maintainState;
+
+  @Deprecated('use keepAlive() instead')
+  set maintainState(bool value);
+
+  /// Requests for the state of a provider to not be disposed when all the
+  /// listeners of the provider are removed.
+  ///
+  /// Returns an object which allows cancelling this operation, therefore
+  /// allowing the provider to dispose itself when all listeners are removed.
+  ///
+  /// If [keepAlive] is invoked multiple times, all [KeepAliveLink] will have
+  /// to be closed for the provider to dispose itself when all listeners are removed.
+  KeepAliveLink keepAlive();
+
+  @override
+  T watch<T>(
+    // can read both auto-dispose and non-auto-dispose providers
+    ProviderListenable<T> provider,
+  );
+
+  @override
+  ProviderSubscription<T> listen<T>(
+    // overridden to allow AutoDisposeProviderBase
+    ProviderListenable<T> provider,
+    void Function(T? previous, T next) listener, {
+    bool fireImmediately,
+    void Function(Object error, StackTrace stackTrace)? onError,
+  });
+}
diff --git a/packages/riverpod/lib/src/framework/scheduler.dart b/packages/riverpod/lib/src/framework/scheduler.dart
index c450d61d3c..874c037cda 100644
--- a/packages/riverpod/lib/src/framework/scheduler.dart
+++ b/packages/riverpod/lib/src/framework/scheduler.dart
@@ -11,7 +11,7 @@ class _ProviderScheduler {
 
   final void Function(void Function() onDone) vsync;
 
-  final _stateToDispose = <AutoDisposeProviderElementBase>[];
+  final _stateToDispose = <AutoDisposeProviderElementMixin>[];
   final _stateToRefresh = <ProviderElementBase>[];
 
   Completer<void>? _pendingTaskCompleter;
@@ -50,7 +50,7 @@ class _ProviderScheduler {
     }
   }
 
-  void scheduleProviderDispose(AutoDisposeProviderElementBase element) {
+  void scheduleProviderDispose(AutoDisposeProviderElementMixin element) {
     assert(
       !element.hasListeners,
       'Tried to dispose ${element._provider} , but still has listeners',
@@ -69,9 +69,11 @@ class _ProviderScheduler {
     for (var i = 0; i < _stateToDispose.length; i++) {
       final element = _stateToDispose[i];
 
+      final links = element._keepAliveLinks;
+
       // ignore: deprecated_member_use_from_same_package
       if (element.maintainState ||
-          element._keepAliveLinks.isNotEmpty ||
+          (links != null && links.isNotEmpty) ||
           element.hasListeners ||
           element._container._disposed) {
         continue;
diff --git a/packages/riverpod/lib/src/framework/selector.dart b/packages/riverpod/lib/src/framework/selector.dart
index a638e25e2b..b21e672992 100644
--- a/packages/riverpod/lib/src/framework/selector.dart
+++ b/packages/riverpod/lib/src/framework/selector.dart
@@ -21,7 +21,8 @@ abstract class Node {
     ProviderBase<State> provider,
   );
 
-  ProviderSubscription<State> _createSubscription<State>(
+  /// Subscribes to a [ProviderElementBase].
+  ProviderSubscription<State> _listenElement<State>(
     ProviderElementBase<State> element, {
     required void Function(State? previous, State next) listener,
     required void Function(Object error, StackTrace stackTrace) onError,
@@ -98,8 +99,9 @@ class _ProviderSelector<Input, Output> with ProviderListenable<Output> {
   _SelectorSubscription<Input, Output> addListener(
     Node node,
     void Function(Output? previous, Output next) listener, {
-    void Function(Object error, StackTrace stackTrace)? onError,
-    bool fireImmediately = false,
+    required void Function(Object error, StackTrace stackTrace)? onError,
+    required void Function()? onDependencyMayHaveChanged,
+    required bool fireImmediately,
   }) {
     onError ??= Zone.current.handleUncaughtError;
 
@@ -142,6 +144,12 @@ class _ProviderSelector<Input, Output> with ProviderListenable<Output> {
       },
     );
   }
+
+  @override
+  Output read(Node node) {
+    final input = provider.read(node);
+    return selector(input);
+  }
 }
 
 class _SelectorSubscription<Input, Output>
@@ -171,3 +179,6 @@ class _SelectorSubscription<Input, Output>
     return _read();
   }
 }
+
+class _AlwaysAliveProviderSelector<Input, Output> = _ProviderSelector<Input,
+    Output> with AlwaysAliveProviderListenable<Output>;
diff --git a/packages/riverpod/lib/src/future_provider.dart b/packages/riverpod/lib/src/future_provider.dart
index 4b84a7b06e..87252bca16 100644
--- a/packages/riverpod/lib/src/future_provider.dart
+++ b/packages/riverpod/lib/src/future_provider.dart
@@ -1,17 +1,39 @@
 import 'dart:async';
 
-import 'package:meta/meta.dart';
-import 'async_value_converters.dart';
-
 import 'builders.dart';
 import 'common.dart';
 import 'framework.dart';
-import 'provider.dart';
-import 'stream_provider.dart';
+import 'listenable.dart';
+import 'provider.dart' show Provider;
+import 'result.dart';
+import 'stream_provider.dart' show StreamProvider;
+import 'synchronous_future.dart';
 
 part 'future_provider/auto_dispose.dart';
 part 'future_provider/base.dart';
 
+ProviderElementProxy<AsyncValue<T>, Future<T>> _future<T>(
+  _FutureProviderBase<T> that,
+) {
+  return ProviderElementProxy<AsyncValue<T>, Future<T>>(
+    that,
+    (element) {
+      return (element as FutureProviderElement<T>)._futureNotifier;
+    },
+  );
+}
+
+ProviderElementProxy<AsyncValue<T>, Stream<T>> _stream<T>(
+  _FutureProviderBase<T> that,
+) {
+  return ProviderElementProxy<AsyncValue<T>, Stream<T>>(
+    that,
+    (element) {
+      return (element as FutureProviderElement<T>)._streamNotifier;
+    },
+  );
+}
+
 /// {@template riverpod.futureprovider}
 /// A provider that asynchronously creates a single value.
 ///
@@ -78,39 +100,58 @@ part 'future_provider/base.dart';
 /// - [FutureProvider.family], to create a [FutureProvider] from external parameters
 /// - [FutureProvider.autoDispose], to destroy the state of a [FutureProvider] when no longer needed.
 /// {@endtemplate}
-mixin _FutureProviderElementMixin<State>
-    on ProviderElementBase<AsyncValue<State>> {
-  AsyncValue<State> _listenFuture(
-    FutureOr<State> Function() future,
-  ) {
-    var running = true;
-    onDispose(() => running = false);
-    try {
-      final value = future();
+abstract class _FutureProviderBase<T> extends ProviderBase<AsyncValue<T>> {
+  _FutureProviderBase({
+    required this.dependencies,
+    required super.name,
+    required super.from,
+    required super.argument,
+    required super.cacheTime,
+    required super.disposeDelay,
+  });
+
+  @override
+  final List<ProviderOrFamily>? dependencies;
+
+  /// Obtains the [Future] associated with a [FutureProvider].
+  ///
+  /// The instance of [Future] obtained may change over time, if the provider
+  /// was recreated (such as when using [Ref.watch]).
+  ///
+  /// This provider allows using `async`/`await` to easily combine
+  /// [FutureProvider] together:
+  ///
+  /// ```dart
+  /// final configsProvider = FutureProvider((ref) async => Configs());
+  ///
+  /// final productsProvider = FutureProvider((ref) async {
+  ///   // Wait for the configurations to resolve
+  ///   final configs = await ref.watch(configsProvider.future);
+  ///
+  ///   // Do something with the result
+  ///   return await http.get('${configs.host}/products');
+  /// });
+  /// ```
+  ProviderListenable<Future<T>> get future;
+
+  /// Obtains a [Stream] representation of this provider.
+  ///
+  /// The stream will not emit a value until the future returned by this [FutureProvider]
+  /// resolves at least once.
+  /// Errors inside the providers will be sent to the stream.
+  ///
+  /// If you want to listen to this provider, consider using `ref.listen(futureProvider)` instead.
+  ProviderListenable<Stream<T>> get stream;
+
+  FutureOr<T> _create(covariant FutureProviderElement<T> ref);
 
-      if (value is Future<State>) {
-        setState(AsyncValue<State>.loading());
+  @override
+  bool updateShouldNotify(AsyncValue<T> previousState, AsyncValue<T> newState) {
+    final wasLoading = previousState is AsyncLoading;
+    final isLoading = newState is AsyncLoading;
 
-        value.then(
-          (event) {
-            if (running) setState(AsyncValue<State>.data(event));
-          },
-          // ignore: avoid_types_on_closure_parameters
-          onError: (Object err, StackTrace stack) {
-            if (running) {
-              setState(
-                AsyncValue<State>.error(err, stackTrace: stack),
-              );
-            }
-          },
-        );
-      } else {
-        return AsyncData(value);
-      }
+    if (wasLoading || isLoading) return wasLoading != isLoading;
 
-      return requireState;
-    } catch (err, stack) {
-      return AsyncValue.error(err, stackTrace: stack);
-    }
+    return true;
   }
 }
diff --git a/packages/riverpod/lib/src/future_provider/auto_dispose.dart b/packages/riverpod/lib/src/future_provider/auto_dispose.dart
index fba0cfa7b0..528cd7f924 100644
--- a/packages/riverpod/lib/src/future_provider/auto_dispose.dart
+++ b/packages/riverpod/lib/src/future_provider/auto_dispose.dart
@@ -1,156 +1,64 @@
 part of '../future_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
-/// - [ProviderRef.state], the value currently exposed by this provider.
+/// - [FutureProviderRef.state], the value currently exposed by this provider.
 abstract class AutoDisposeFutureProviderRef<State>
-    implements AutoDisposeRef<AsyncValue<State>> {
-  /// Obtains the state currently exposed by this provider.
-  ///
-  /// Mutating this property will notify the provider listeners.
-  ///
-  /// Cannot be called while a provider is creating, unless the setter was called first.
-  ///
-  /// Will throw if the provider threw during creation.
-  AsyncValue<State> get state;
-  set state(AsyncValue<State> newState);
-}
+    extends FutureProviderRef<State>
+    implements AutoDisposeRef<AsyncValue<State>> {}
 
 /// {@macro riverpod.futureprovider}
-@sealed
-class AutoDisposeFutureProvider<State>
-    extends AutoDisposeProviderBase<AsyncValue<State>>
-    with
-        OverrideWithValueMixin<AsyncValue<State>>,
-        OverrideWithProviderMixin<AsyncValue<State>,
-            AutoDisposeProviderBase<AsyncValue<State>>> {
+class AutoDisposeFutureProvider<T> extends _FutureProviderBase<T>
+    with AsyncSelector<T> {
   /// {@macro riverpod.futureprovider}
   AutoDisposeFutureProvider(
-    this._create, {
-    String? name,
-    this.dependencies,
-    Family? from,
-    Object? argument,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  });
 
   /// {@macro riverpod.family}
-  static const family = AutoDisposeFutureProviderFamilyBuilder();
-
-  final Create<FutureOr<State>, AutoDisposeFutureProviderRef<State>> _create;
+  static const family = AutoDisposeFutureProviderFamily.new;
 
-  @override
-  final List<ProviderOrFamily>? dependencies;
+  final FutureOr<T> Function(AutoDisposeFutureProviderRef<T> ref) _createFn;
 
   @override
-  ProviderBase<AsyncValue<State>> get originProvider => this;
-
-  /// {@macro riverpod.futureprovider.future}
-  late final AutoDisposeProviderBase<Future<State>> future =
-      AutoDisposeAsyncValueAsFutureProvider(
-    this,
-    from: from,
-    argument: argument,
-    cacheTime: cacheTime,
-    disposeDelay: disposeDelay,
-  );
+  FutureOr<T> _create(AutoDisposeFutureProviderElement<T> ref) =>
+      _createFn(ref);
 
   @override
-  AsyncValue<State> create(
-    covariant AutoDisposeFutureProviderElement<State> ref,
-  ) {
-    return ref._listenFuture(() => _create(ref));
+  AutoDisposeFutureProviderElement<T> createElement() {
+    return AutoDisposeFutureProviderElement._(this);
   }
 
   @override
-  bool updateShouldNotify(
-    AsyncValue<State> previousState,
-    AsyncValue<State> newState,
-  ) {
-    final wasLoading = previousState is AsyncLoading;
-    final isLoading = newState is AsyncLoading;
-
-    if (wasLoading || isLoading) return wasLoading != isLoading;
-
-    return true;
-  }
+  late final Refreshable<Future<T>> future = _future(this);
 
   @override
-  AutoDisposeFutureProviderElement<State> createElement() {
-    return AutoDisposeFutureProviderElement(this);
-  }
+  late final Refreshable<Stream<T>> stream = _stream(this);
 }
 
-/// The element of an [AutoDisposeFutureProvider]
-class AutoDisposeFutureProviderElement<State>
-    extends AutoDisposeProviderElementBase<AsyncValue<State>>
-    with _FutureProviderElementMixin<State>
-    implements AutoDisposeFutureProviderRef<State> {
-  /// The element of an [AutoDisposeFutureProvider]
-  AutoDisposeFutureProviderElement(AutoDisposeFutureProvider<State> provider)
-      : super(provider);
-
-  @override
-  AsyncValue<State> get state => requireState;
-
-  @override
-  set state(AsyncValue<State> newState) => setState(newState);
-}
-
-/// {@template riverpod.futureprovider.family}
-/// A class that allows building an [AutoDisposeFutureProvider] from an external parameter.
-/// {@endtemplate}
-@sealed
-class AutoDisposeFutureProviderFamily<State, Arg>
-    extends Family<AsyncValue<State>, Arg, AutoDisposeFutureProvider<State>> {
-  /// {@macro riverpod.futureprovider.family}
+/// The [ProviderElementBase] of [AutoDisposeFutureProvider]
+class AutoDisposeFutureProviderElement<T> = FutureProviderElement<T>
+    with AutoDisposeProviderElementMixin<AsyncValue<T>>
+    implements AutoDisposeFutureProviderRef<T>;
+
+/// The [Family] of an [AutoDisposeFutureProvider]
+class AutoDisposeFutureProviderFamily<R, Arg> extends AutoDisposeFamilyBase<
+    AutoDisposeFutureProviderRef<R>,
+    AsyncValue<R>,
+    Arg,
+    FutureOr<R>,
+    AutoDisposeFutureProvider<R>> {
+  /// The [Family] of an [AutoDisposeFutureProvider]
   AutoDisposeFutureProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          dependencies: dependencies,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final FamilyCreate<FutureOr<State>, AutoDisposeFutureProviderRef<State>, Arg>
-      _create;
-
-  @override
-  AutoDisposeFutureProvider<State> create(Arg argument) {
-    return AutoDisposeFutureProvider<State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-      cacheTime: cacheTime,
-      disposeDelay: disposeDelay,
-    );
-  }
-
-  @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final futureProvider = call(argument);
-    setup(origin: futureProvider, override: futureProvider);
-  }
-
-  /// {@macro riverpod.overridewithprovider}
-  Override overrideWithProvider(
-    AutoDisposeProviderBase<AsyncValue<State>> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(this, (arg, setup) {
-      final futureProvider = call(arg);
-      setup(origin: futureProvider, override: override(arg));
-    });
-  }
+    super.create, {
+    super.name,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  }) : super(providerFactory: AutoDisposeFutureProvider.new);
 }
diff --git a/packages/riverpod/lib/src/future_provider/base.dart b/packages/riverpod/lib/src/future_provider/base.dart
index 8e79b7991e..2b4fde20eb 100644
--- a/packages/riverpod/lib/src/future_provider/base.dart
+++ b/packages/riverpod/lib/src/future_provider/base.dart
@@ -1,7 +1,7 @@
 part of '../future_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
-/// - [ProviderRef.state], the value currently exposed by this provider.
+/// - [state], the value currently exposed by this provider.
 abstract class FutureProviderRef<State> implements Ref<AsyncValue<State>> {
   /// Obtains the state currently exposed by this provider.
   ///
@@ -15,136 +15,134 @@ abstract class FutureProviderRef<State> implements Ref<AsyncValue<State>> {
 }
 
 /// {@macro riverpod.futureprovider}
-@sealed
-class FutureProvider<State> extends AlwaysAliveProviderBase<AsyncValue<State>>
-    with
-        OverrideWithValueMixin<AsyncValue<State>>,
-        OverrideWithProviderMixin<AsyncValue<State>,
-            AlwaysAliveProviderBase<AsyncValue<State>>> {
+class FutureProvider<T> extends _FutureProviderBase<T>
+    with AlwaysAliveProviderBase<AsyncValue<T>>, AlwaysAliveAsyncSelector<T> {
   /// {@macro riverpod.futureprovider}
   FutureProvider(
-    this._create, {
-    String? name,
-    this.dependencies,
-    Family? from,
-    Object? argument,
-  }) : super(name: name, from: from, argument: argument);
-
-  /// {@macro riverpod.family}
-  static const family = FutureProviderFamilyBuilder();
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+  }) : super(cacheTime: null, disposeDelay: null);
 
   /// {@macro riverpod.autoDispose}
   static const autoDispose = AutoDisposeFutureProviderBuilder();
 
-  @override
-  ProviderBase<AsyncValue<State>> get originProvider => this;
-
-  @override
-  final List<ProviderOrFamily>? dependencies;
-
-  final Create<FutureOr<State>, FutureProviderRef<State>> _create;
+  /// {@macro riverpod.family}
+  static const family = FutureProviderFamilyBuilder();
 
-  /// {@template riverpod.futureprovider.future}
-  /// A provider that exposes the [Future] created by a [FutureProvider].
-  ///
-  /// The instance of [Future] obtained may change over time, if the provider
-  /// was recreated (such as when using [Ref.watch]).
-  ///
-  /// This provider allows using `async`/`await` to easily combine
-  /// [FutureProvider] together:
-  ///
-  /// ```dart
-  /// final configsProvider = FutureProvider((ref) async => Configs());
-  ///
-  /// final productsProvider = FutureProvider((ref) async {
-  ///   // Wait for the configurations to resolve
-  ///   final configs = await ref.watch(configsProvider.future);
-  ///
-  ///   // Do something with the result
-  ///   return await http.get('${configs.host}/products');
-  /// });
-  /// ```
-  /// {@endtemplate}
-  late final AlwaysAliveProviderBase<Future<State>> future =
-      AsyncValueAsFutureProvider(this, from: from, argument: argument);
+  final FutureOr<T> Function(FutureProviderRef<T> ref) _createFn;
 
   @override
-  AsyncValue<State> create(
-    covariant FutureProviderElement<State> ref,
-  ) {
-    return ref._listenFuture(() => _create(ref));
-  }
+  late final AlwaysAliveRefreshable<Future<T>> future = _future(this);
 
   @override
-  bool updateShouldNotify(
-    AsyncValue<State> previousState,
-    AsyncValue<State> newState,
-  ) {
-    final wasLoading = previousState is AsyncLoading;
-    final isLoading = newState is AsyncLoading;
-
-    if (wasLoading || isLoading) return wasLoading != isLoading;
+  late final AlwaysAliveRefreshable<Stream<T>> stream = _stream(this);
 
-    return true;
-  }
+  @override
+  FutureOr<T> _create(FutureProviderElement<T> ref) => _createFn(ref);
 
   @override
-  FutureProviderElement<State> createElement() => FutureProviderElement(this);
+  FutureProviderElement<T> createElement() => FutureProviderElement._(this);
 }
 
 /// The element of a [FutureProvider]
-class FutureProviderElement<State>
-    extends ProviderElementBase<AsyncValue<State>>
-    with _FutureProviderElementMixin<State>
-    implements FutureProviderRef<State> {
-  /// The element of a [FutureProvider]
-  FutureProviderElement(FutureProvider<State> provider) : super(provider);
+class FutureProviderElement<T> extends ProviderElementBase<AsyncValue<T>>
+    implements FutureProviderRef<T> {
+  FutureProviderElement._(_FutureProviderBase<T> provider) : super(provider);
+
+  final _futureNotifier = ProxyElementValueNotifier<Future<T>>();
+  final _streamNotifier = ProxyElementValueNotifier<Stream<T>>();
+  final _streamController = StreamController<T>.broadcast();
 
   @override
-  AsyncValue<State> get state => requireState;
+  AsyncValue<T> get state => requireState;
 
   @override
-  set state(AsyncValue<State> newState) => setState(newState);
-}
+  set state(AsyncValue<T> state) => setState(state);
 
-/// {@template riverpod.futureprovider.family}
-/// A class that allows building a [FutureProvider] from an external parameter.
-/// {@endtemplate}
-@sealed
-class FutureProviderFamily<State, Arg>
-    extends Family<AsyncValue<State>, Arg, FutureProvider<State>> {
-  /// {@macro riverpod.futureprovider.family}
-  FutureProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-  }) : super(name: name, dependencies: dependencies);
+  @override
+  void create() {
+    // TODO add a Proxy variant that accepts T instead of Result<T>
+    _streamNotifier.result ??= Result.data(_streamController.stream);
+
+    // The try/catch is here to handle synchronous exceptions, which can happen
+    // if the create function isn't marked with "async".
+    try {
+      final provider = this.provider as _FutureProviderBase<T>;
+      final futureOr = provider._create(this);
+
+      final future =
+          futureOr is Future<T> ? futureOr : SynchronousFuture(futureOr);
+
+      if (future != _futureNotifier.result?.stateOrNull) {
+        _futureNotifier.result = Result.data(future);
+        _listenFuture(future);
+      }
+    } catch (err, stack) {
+      // TODO Can we have a SynchronousFutureError?
+      _futureNotifier.result = Result.data(
+        Future.error(err, stack)
+          // TODO report the error to the ProviderContainer's Zone
+          ..ignore(),
+      );
+      _streamController.addError(err, stack);
+      setState(AsyncError<T>(err, stackTrace: stack));
+    }
+  }
 
-  final FamilyCreate<FutureOr<State>, FutureProviderRef<State>, Arg> _create;
+  @pragma('vm:prefer-inline')
+  void _listenFuture(Future<T> future) {
+    var running = true;
+    onDispose(() => running = false);
+
+    setState(AsyncLoading<T>());
+
+    future.then(
+      (value) {
+        if (running) {
+          _streamController.add(value);
+          setState(AsyncData<T>(value));
+        }
+      },
+      // ignore: avoid_types_on_closure_parameters
+      onError: (Object err, StackTrace stack) {
+        if (running) {
+          _streamController.addError(err, stack);
+          setState(AsyncError<T>(err, stackTrace: stack));
+        }
+      },
+    );
+  }
 
   @override
-  FutureProvider<State> create(Arg argument) {
-    return FutureProvider<State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
+  void visitChildren({
+    required void Function(ProviderElementBase element) elementVisitor,
+    required void Function(ProxyElementValueNotifier element) notifierVisitor,
+  }) {
+    super.visitChildren(
+      elementVisitor: elementVisitor,
+      notifierVisitor: notifierVisitor,
     );
+    notifierVisitor(_futureNotifier);
+    notifierVisitor(_streamNotifier);
   }
 
   @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final futureProvider = call(argument);
-    setup(origin: futureProvider, override: futureProvider);
+  void dispose() {
+    _streamController.close();
+    super.dispose();
   }
+}
 
-  /// {@macro riverpod.overridewithprovider}
-  Override overrideWithProvider(
-    AlwaysAliveProviderBase<AsyncValue<State>> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(this, (arg, setup) {
-      final futureProvider = call(arg);
-      setup(origin: futureProvider, override: override(arg));
-    });
-  }
+/// The [Family] of a [FutureProvider]
+class FutureProviderFamily<R, Arg> extends FamilyBase<FutureProviderRef<R>,
+    AsyncValue<R>, Arg, FutureOr<R>, FutureProvider<R>> {
+  /// The [Family] of a [FutureProvider]
+  FutureProviderFamily(
+    super.create, {
+    super.name,
+    super.dependencies,
+  }) : super(providerFactory: FutureProvider<R>.new);
 }
diff --git a/packages/riverpod/lib/src/internals.dart b/packages/riverpod/lib/src/internals.dart
index e95547901d..1c248c54d8 100644
--- a/packages/riverpod/lib/src/internals.dart
+++ b/packages/riverpod/lib/src/internals.dart
@@ -9,7 +9,10 @@ export 'builders.dart';
 export 'common.dart';
 export 'framework.dart';
 export 'future_provider.dart';
+export 'listenable.dart';
 export 'provider.dart';
+export 'result.dart';
+export 'run_guarded.dart';
 export 'state_notifier_provider.dart';
 export 'state_provider.dart';
 export 'stream_provider.dart';
diff --git a/packages/riverpod/lib/src/listenable.dart b/packages/riverpod/lib/src/listenable.dart
new file mode 100644
index 0000000000..21614bb025
--- /dev/null
+++ b/packages/riverpod/lib/src/listenable.dart
@@ -0,0 +1,338 @@
+import 'package:meta/meta.dart';
+
+import 'framework.dart' show ProviderElementBase;
+import 'result.dart';
+
+/// Listener for [_ValueListenable]
+class _Listener<T> {
+  _Listener._(this.onValue, this.onError, this.onDependencyMayHaveChanged);
+
+  final void Function(T? previous, T next) onValue;
+  final void Function(Object error, StackTrace stackTrace)? onError;
+  final void Function()? onDependencyMayHaveChanged;
+}
+
+/// A listenable object used by [ProviderElementBase] as a mean to subscribe
+/// to subsets of the state exposed by a provider.
+class ProxyElementValueNotifier<T> extends _ValueListenable<T> {
+  /// Directly obtain the value exposed, grafully handling cases where
+  /// [result] is null or in error state.
+  T get value {
+    final result = _result;
+    if (result == null) {
+      throw StateError('Trying to read an uninitialized value.');
+    }
+    return result.requireState;
+  }
+
+  /// The state associated with this notifier.
+  ///
+  /// Modifying this property will notify listeners.
+  Result<T>? get result => _result;
+  Result<T>? _result;
+  set result(Result<T>? value) {
+    final previous = _result;
+    _result = value;
+    value?.when(
+      data: (newValue) => _notifyValue(previous?.stateOrNull, newValue),
+      error: _notifyError,
+    );
+  }
+
+  /// Updates the [result] of this [ProxyElementValueNotifier] without invoking listeners.
+  // ignore: use_setters_to_change_properties, non_constant_identifier_names
+  void UNSAFE_setResultWithoutNotifyingListeners(Result<T>? value) {
+    _result = value;
+  }
+}
+
+class _ValueListenable<T> {
+  int _count = 0;
+  // The _listeners is intentionally set to a fixed-length _GrowableList instead
+  // of const [].
+  //
+  // The const [] creates an instance of _ImmutableList which would be
+  // different from fixed-length _GrowableList used elsewhere in this class.
+  // keeping runtime type the same during the lifetime of this class lets the
+  // compiler to infer concrete type for this property, and thus improves
+  // performance.
+  static List<_Listener<T>?> _emptyListeners<T>() =>
+      List<_Listener<T>?>.filled(0, null);
+
+  List<_Listener<T>?> _listeners = _emptyListeners();
+  int _notificationCallStackDepth = 0;
+  int _reentrantlyRemovedListeners = 0;
+  bool _debugDisposed = false;
+
+  static bool debugAssertNotDisposed(_ValueListenable notifier) {
+    assert(
+      !notifier._debugDisposed,
+      'A ${notifier.runtimeType} was used after being disposed.\n'
+      'Once you have called dispose() on a ${notifier.runtimeType}, it '
+      'can no longer be used.',
+    );
+    return true;
+  }
+
+  /// Whether any listeners are currently registered.
+  ///
+  /// Clients should not depend on this value for their behavior, because having
+  /// one listener's logic change when another listener happens to start or stop
+  /// listening will lead to extremely hard-to-track bugs. Subclasses might use
+  /// this information to determine whether to do any work when there are no
+  /// listeners, however; for example, resuming a [Stream] when a listener is
+  /// added and pausing it when a listener is removed.
+  ///
+  /// Typically this is used by overriding [addListener], checking if
+  /// [hasListeners] is false before calling `super.addListener()`, and if so,
+  /// starting whatever work is needed to determine when to call
+  /// [_notifyListeners]; and similarly, by overriding [_removeListener], checking
+  /// if [hasListeners] is false after calling `super.removeListener()`, and if
+  /// so, stopping that same work.
+  @protected
+  bool get hasListeners {
+    return _count > 0;
+  }
+
+  /// Register a closure to be called when the object changes.
+  ///
+  /// If the given closure is already registered, an additional instance is
+  /// added, and must be removed the same number of times it is added before it
+  /// will stop being called.
+  ///
+  /// This method must not be called after [dispose] has been called.
+  ///
+  /// {@template flutter.foundation._ChangeNotifier.addListener}
+  /// If a listener is added twice, and is removed once during an iteration
+  /// (e.g. in response to a notification), it will still be called again. If,
+  /// on the other hand, it is removed as many times as it was registered, then
+  /// it will no longer be called. This odd behavior is the result of the
+  /// [_ValueListenable] not being able to determine which listener is being
+  /// removed, since they are identical, therefore it will conservatively still
+  /// call all the listeners when it knows that any are still registered.
+  ///
+  /// This surprising behavior can be unexpectedly observed when registering a
+  /// listener on two separate objects which are both forwarding all
+  /// registrations to a common upstream object.
+  /// {@endtemplate}
+  ///
+  /// See also:
+  ///
+  ///  * [_removeListener], which removes a previously registered closure from
+  ///    the list of closures that are notified when the object changes.
+  void Function() addListener(
+    void Function(T?, T) onChange, {
+    required void Function(Object, StackTrace)? onError,
+    required void Function()? onDependencyMayHaveChanged,
+  }) {
+    assert(_ValueListenable.debugAssertNotDisposed(this), '');
+
+    final listener = _Listener._(onChange, onError, onDependencyMayHaveChanged);
+    if (_count == _listeners.length) {
+      if (_count == 0) {
+        _listeners = List<_Listener<T>?>.filled(1, null);
+      } else {
+        final newListeners =
+            List<_Listener<T>?>.filled(_listeners.length * 2, null);
+        for (var i = 0; i < _count; i++) {
+          newListeners[i] = _listeners[i];
+        }
+        _listeners = newListeners;
+      }
+    }
+    _listeners[_count++] = listener;
+
+    return () => _removeListener(listener);
+  }
+
+  void _removeAt(int index) {
+    // The list holding the listeners is not growable for performances reasons.
+    // We still want to shrink this list if a lot of listeners have been added
+    // and then removed outside a _notifyListeners iteration.
+    // We do this only when the real number of listeners is half the length
+    // of our list.
+    _count -= 1;
+    if (_count * 2 <= _listeners.length) {
+      final newListeners = List<_Listener<T>?>.filled(_count, null);
+
+      // Listeners before the index are at the same place.
+      for (var i = 0; i < index; i++) {
+        newListeners[i] = _listeners[i];
+      }
+
+      // Listeners after the index move towards the start of the list.
+      for (var i = index; i < _count; i++) {
+        newListeners[i] = _listeners[i + 1];
+      }
+
+      _listeners = newListeners;
+    } else {
+      // When there are more listeners than half the length of the list, we only
+      // shift our listeners, so that we avoid to reallocate memory for the
+      // whole list.
+      for (var i = index; i < _count; i++) {
+        _listeners[i] = _listeners[i + 1];
+      }
+      _listeners[_count] = null;
+    }
+  }
+
+  /// Remove a previously registered closure from the list of closures that are
+  /// notified when the object changes.
+  ///
+  /// If the given listener is not registered, the call is ignored.
+  ///
+  /// This method returns immediately if [dispose] has been called.
+  ///
+  /// {@macro flutter.foundation._ChangeNotifier.addListener}
+  ///
+  /// See also:
+  ///
+  ///  * [addListener], which registers a closure to be called when the object
+  ///    changes.
+  void _removeListener(_Listener<T> listener) {
+    // This method is allowed to be called on disposed instances for usability
+    // reasons. Due to how our frame scheduling logic between render objects and
+    // overlays, it is common that the owner of this instance would be disposed a
+    // frame earlier than the listeners. Allowing calls to this method after it
+    // is disposed makes it easier for listeners to properly clean up.
+    for (var i = 0; i < _count; i++) {
+      final listenerAtIndex = _listeners[i];
+      if (listenerAtIndex == listener) {
+        if (_notificationCallStackDepth > 0) {
+          // We don't resize the list during _notifyListeners iterations
+          // but we set to null, the listeners we want to remove. We will
+          // effectively resize the list at the end of all _notifyListeners
+          // iterations.
+          _listeners[i] = null;
+          _reentrantlyRemovedListeners++;
+        } else {
+          // When we are outside the _notifyListeners iterations we can
+          // effectively shrink the list.
+          _removeAt(i);
+        }
+        break;
+      }
+    }
+  }
+
+  /// Discards any resources used by the object. After this is called, the
+  /// object is not in a usable state and should be discarded (calls to
+  /// [addListener] will throw after the object is disposed).
+  ///
+  /// This method should only be called by the object's owner.
+  ///
+  /// This method does not notify listeners, and clears the listener list once
+  /// it is called. Consumers of this class must decide on whether to notify
+  /// listeners or not immediately before disposal.
+  @mustCallSuper
+  void dispose() {
+    assert(() {
+      _debugDisposed = true;
+      return true;
+    }(), '');
+    _listeners = _emptyListeners();
+    _count = 0;
+  }
+
+  /// Call all the registered listeners.
+  ///
+  /// Call this method whenever the object changes, to notify any clients the
+  /// object may have changed. Listeners that are added during this iteration
+  /// will not be visited. Listeners that are removed during this iteration will
+  /// not be visited after they are removed.
+  ///
+  /// Listeners should not throw.
+  ///
+  /// This method must not be called after [dispose] has been called.
+  ///
+  /// Surprising behavior can result when reentrantly removing a listener (e.g.
+  /// in response to a notification) that has been registered multiple times.
+  /// See the discussion at [_removeListener].
+  @protected
+  @pragma('vm:notify-debugger-on-exception')
+  void _notifyListeners(void Function(_Listener<T> listener) notify) {
+    assert(_ValueListenable.debugAssertNotDisposed(this), '');
+    if (_count == 0) {
+      return;
+    }
+
+    // To make sure that listeners removed during this iteration are not called,
+    // we set them to null, but we don't shrink the list right away.
+    // By doing this, we can continue to iterate on our list until it reaches
+    // the last listener added before the call to this method.
+
+    // To allow potential listeners to recursively call notifyListener, we track
+    // the number of times this method is called in _notificationCallStackDepth.
+    // Once every recursive iteration is finished (i.e. when _notificationCallStackDepth == 0),
+    // we can safely shrink our list so that it will only contain not null
+    // listeners.
+
+    _notificationCallStackDepth++;
+
+    final end = _count;
+    for (var i = 0; i < end; i++) {
+      try {
+        final listener = _listeners[i];
+        if (listener != null) {
+          notify(listener);
+        }
+      } catch (exception, stack) {
+        throw StateError(
+          'An exception was thrown inside a _ChangeNotifier listener:'
+          '\n$exception\n$stack',
+        );
+      }
+    }
+
+    _notificationCallStackDepth--;
+
+    if (_notificationCallStackDepth == 0 && _reentrantlyRemovedListeners > 0) {
+      // We really remove the listeners when all notifications are done.
+      final newLength = _count - _reentrantlyRemovedListeners;
+      if (newLength * 2 <= _listeners.length) {
+        // As in _removeAt, we only shrink the list when the real number of
+        // listeners is half the length of our list.
+        final newListeners = List<_Listener<T>?>.filled(newLength, null);
+
+        var newIndex = 0;
+        for (var i = 0; i < _count; i++) {
+          final listener = _listeners[i];
+          if (listener != null) {
+            newListeners[newIndex++] = listener;
+          }
+        }
+
+        _listeners = newListeners;
+      } else {
+        // Otherwise we put all the null references at the end.
+        for (var i = 0; i < newLength; i += 1) {
+          if (_listeners[i] == null) {
+            // We swap this item with the next not null item.
+            var swapIndex = i + 1;
+            while (_listeners[swapIndex] == null) {
+              swapIndex += 1;
+            }
+            _listeners[i] = _listeners[swapIndex];
+            _listeners[swapIndex] = null;
+          }
+        }
+      }
+
+      _reentrantlyRemovedListeners = 0;
+      _count = newLength;
+    }
+  }
+
+  void _notifyValue(T? prev, T next) {
+    _notifyListeners((listener) => listener.onValue(prev, next));
+  }
+
+  void _notifyError(Object err, StackTrace stack) {
+    _notifyListeners((listener) => listener.onError?.call(err, stack));
+  }
+
+  void notifyDependencyMayHaveChanged() {
+    _notifyListeners((listener) => listener.onDependencyMayHaveChanged?.call());
+  }
+}
diff --git a/packages/riverpod/lib/src/provider.dart b/packages/riverpod/lib/src/provider.dart
index 5129e152bf..6ee3a761e0 100644
--- a/packages/riverpod/lib/src/provider.dart
+++ b/packages/riverpod/lib/src/provider.dart
@@ -1,12 +1,31 @@
-import 'dart:developer' as developer;
-
 import 'package:meta/meta.dart';
 
 import 'builders.dart';
 import 'framework.dart';
-import 'state_notifier_provider.dart';
-import 'stream_provider.dart';
+import 'state_notifier_provider.dart' show StateNotifierProvider;
+import 'stream_provider.dart' show StreamProvider;
 
-part 'devtool.dart';
 part 'provider/auto_dispose.dart';
 part 'provider/base.dart';
+
+abstract class _ProviderBase<State> extends ProviderBase<State>
+    with OverrideWithValueMixin<State> {
+  _ProviderBase({
+    required this.dependencies,
+    required super.name,
+    required super.from,
+    required super.argument,
+    required super.cacheTime,
+    required super.disposeDelay,
+  });
+
+  @override
+  final List<ProviderOrFamily>? dependencies;
+
+  State _create(covariant ProviderElement<State> ref);
+
+  @override
+  bool updateShouldNotify(State previousState, State newState) {
+    return previousState != newState;
+  }
+}
diff --git a/packages/riverpod/lib/src/provider/auto_dispose.dart b/packages/riverpod/lib/src/provider/auto_dispose.dart
index e3065484a1..710f3dc14a 100644
--- a/packages/riverpod/lib/src/provider/auto_dispose.dart
+++ b/packages/riverpod/lib/src/provider/auto_dispose.dart
@@ -1,101 +1,50 @@
 part of '../provider.dart';
 
 /// {@macro riverpod.providerrefbase}
-/// - [state], the value currently exposed by this provider.
-abstract class AutoDisposeProviderRef<State>
-    implements ProviderRef<State>, AutoDisposeRef<State> {}
+abstract class AutoDisposeProviderRef<State> extends ProviderRef<State>
+    implements AutoDisposeRef<State> {}
 
 /// {@macro riverpod.provider}
-@sealed
-class AutoDisposeProvider<State> extends AutoDisposeProviderBase<State>
-    with
-        OverrideWithValueMixin<State>,
-        OverrideWithProviderMixin<State, AutoDisposeProviderBase<State>> {
+class AutoDisposeProvider<T> extends _ProviderBase<T> {
   /// {@macro riverpod.provider}
   AutoDisposeProvider(
-    this._create, {
-    String? name,
-    this.dependencies,
-    Family? from,
-    Object? argument,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  });
 
   /// {@macro riverpod.family}
-  static const family = AutoDisposeProviderFamilyBuilder();
+  static const family = AutoDisposeProviderFamily.new;
 
-  @override
-  ProviderBase<State> get originProvider => this;
-
-  final Create<State, AutoDisposeProviderRef<State>> _create;
-
-  @override
-  final List<ProviderOrFamily>? dependencies;
+  final T Function(AutoDisposeProviderRef<T> ref) _createFn;
 
   @override
-  State create(AutoDisposeProviderRef<State> ref) => _create(ref);
+  T _create(AutoDisposeProviderElement<T> ref) => _createFn(ref);
 
   @override
-  bool updateShouldNotify(State previousState, State newState) {
-    return previousState != newState;
-  }
-
-  @override
-  AutoDisposeProviderElement<State> createElement() {
-    return AutoDisposeProviderElement(this);
+  AutoDisposeProviderElement<T> createElement() {
+    return AutoDisposeProviderElement._(this);
   }
 }
 
-/// An [AutoDisposeProviderElementBase] for [AutoDisposeProvider]
-class AutoDisposeProviderElement<State>
-    extends AutoDisposeProviderElementBase<State>
-    implements AutoDisposeProviderRef<State> {
-  /// An [AutoDisposeProviderElementBase] for [AutoDisposeProvider]
-  AutoDisposeProviderElement(ProviderBase<State> provider) : super(provider);
-
-  @override
-  State get state => requireState;
-
-  @override
-  set state(State newState) => setState(newState);
-}
+/// The element of [AutoDisposeProvider]
+class AutoDisposeProviderElement<T> = ProviderElement<T>
+    with AutoDisposeProviderElementMixin<T>
+    implements AutoDisposeProviderRef<T>;
 
-/// {@macro riverpod.provider.family}
-@sealed
-class AutoDisposeProviderFamily<State, Arg>
-    extends Family<State, Arg, AutoDisposeProvider<State>> {
-  /// {@macro riverpod.provider.family}
+/// The [Family] of [AutoDisposeProvider]
+class AutoDisposeProviderFamily<R, Arg> extends AutoDisposeFamilyBase<
+    AutoDisposeProviderRef<R>, R, Arg, R, AutoDisposeProvider<R>> {
+  /// The [Family] of [AutoDisposeProvider]
   AutoDisposeProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          dependencies: dependencies,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final FamilyCreate<State, AutoDisposeProviderRef<State>, Arg> _create;
-
-  @override
-  AutoDisposeProvider<State> create(Arg argument) {
-    return AutoDisposeProvider<State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-      cacheTime: cacheTime,
-      disposeDelay: disposeDelay,
-    );
-  }
+    super.create, {
+    super.name,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  }) : super(providerFactory: AutoDisposeProvider.new);
 }
diff --git a/packages/riverpod/lib/src/provider/base.dart b/packages/riverpod/lib/src/provider/base.dart
index 83b7ff7ebb..a3e83539fb 100644
--- a/packages/riverpod/lib/src/provider/base.dart
+++ b/packages/riverpod/lib/src/provider/base.dart
@@ -14,6 +14,34 @@ abstract class ProviderRef<State> implements Ref<State> {
   set state(State newState);
 }
 
+/// {@macro riverpod.provider}
+@sealed
+class Provider<State> extends _ProviderBase<State>
+    with AlwaysAliveProviderBase<State> {
+  /// {@macro riverpod.provider}
+  Provider(
+    this._createFn, {
+    super.name,
+    super.dependencies,
+    super.from,
+    super.argument,
+  }) : super(cacheTime: null, disposeDelay: null);
+
+  /// {@macro riverpod.family}
+  static const family = ProviderFamilyBuilder();
+
+  /// {@macro riverpod.autoDispose}
+  static const autoDispose = AutoDisposeProviderBuilder();
+
+  final Create<State, ProviderRef<State>> _createFn;
+
+  @override
+  State _create(ProviderElement<State> ref) => _createFn(ref);
+
+  @override
+  ProviderElement<State> createElement() => ProviderElement._(this);
+}
+
 /// {@template riverpod.provider}
 /// A provider that exposes a read-only value.
 ///
@@ -227,77 +255,29 @@ abstract class ProviderRef<State> implements Ref<State> {
 class ProviderElement<State> extends ProviderElementBase<State>
     implements ProviderRef<State> {
   /// A [ProviderElementBase] for [Provider]
-  ProviderElement(ProviderBase<State> provider) : super(provider);
+  ProviderElement._(_ProviderBase<State> provider) : super(provider);
 
   @override
   State get state => requireState;
 
   @override
   set state(State newState) => setState(newState);
-}
-
-/// {@macro riverpod.provider}
-@sealed
-class Provider<State> extends AlwaysAliveProviderBase<State>
-    with
-        OverrideWithValueMixin<State>,
-        OverrideWithProviderMixin<State, AlwaysAliveProviderBase<State>> {
-  /// {@macro riverpod.provider}
-  Provider(
-    this._create, {
-    String? name,
-    this.dependencies,
-    Family? from,
-    Object? argument,
-  }) : super(name: name, from: from, argument: argument);
-
-  /// {@macro riverpod.family}
-  static const family = ProviderFamilyBuilder();
-
-  /// {@macro riverpod.autoDispose}
-  static const autoDispose = AutoDisposeProviderBuilder();
-
-  @override
-  ProviderBase<State> get originProvider => this;
 
   @override
-  final List<ProviderOrFamily>? dependencies;
+  void create() {
+    final provider = this.provider as _ProviderBase<State>;
 
-  final Create<State, ProviderRef<State>> _create;
-
-  @override
-  State create(ProviderRef<State> ref) => _create(ref);
-
-  @override
-  bool updateShouldNotify(State previousState, State newState) {
-    return previousState != newState;
+    setState(provider._create(this));
   }
-
-  @override
-  ProviderElement<State> createElement() => ProviderElement(this);
 }
 
-/// {@template riverpod.provider.family}
-/// A class that allows building a [Provider] from an external parameter.
-/// {@endtemplate}
-@sealed
-class ProviderFamily<State, Arg> extends Family<State, Arg, Provider<State>> {
-  /// {@macro riverpod.provider.family}
+/// The [Family] of [Provider]
+class ProviderFamily<R, Arg>
+    extends FamilyBase<ProviderRef<R>, R, Arg, R, Provider<R>> {
+  /// The [Family] of [ProviderFamily]
   ProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-  }) : super(name: name, dependencies: dependencies);
-
-  final FamilyCreate<State, ProviderRef<State>, Arg> _create;
-
-  @override
-  Provider<State> create(Arg argument) {
-    return Provider<State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-    );
-  }
+    super.create, {
+    super.name,
+    super.dependencies,
+  }) : super(providerFactory: Provider.new);
 }
diff --git a/packages/riverpod/lib/src/result.dart b/packages/riverpod/lib/src/result.dart
index 8b13789179..19f5fbf500 100644
--- a/packages/riverpod/lib/src/result.dart
+++ b/packages/riverpod/lib/src/result.dart
@@ -1,1 +1,120 @@
+// ignore_for_file: public_member_api_docs
 
+import 'package:meta/meta.dart';
+
+@immutable
+abstract class Result<State> {
+  // coverage:ignore-start
+  factory Result.data(State state) = ResultData;
+  // coverage:ignore-end
+
+  // coverage:ignore-start
+  factory Result.error(Object error, StackTrace stackTrace) = ResultError;
+  // coverage:ignore-end
+
+  static Result<State> guard<State>(State Function() cb) {
+    try {
+      return Result.data(cb());
+    } catch (err, stack) {
+      return Result.error(err, stack);
+    }
+  }
+
+  bool get hasState;
+
+  State? get stateOrNull;
+  State get requireState;
+
+  R map<R>({
+    required R Function(ResultData<State> data) data,
+    required R Function(ResultError<State>) error,
+  });
+
+  R when<R>({
+    required R Function(State data) data,
+    required R Function(Object error, StackTrace stackTrace) error,
+  });
+}
+
+class ResultData<State> implements Result<State> {
+  ResultData(this.state);
+
+  final State state;
+
+  @override
+  bool get hasState => true;
+
+  @override
+  State? get stateOrNull => state;
+
+  @override
+  State get requireState => state;
+
+  @override
+  R map<R>({
+    required R Function(ResultData<State> data) data,
+    required R Function(ResultError<State>) error,
+  }) {
+    return data(this);
+  }
+
+  @override
+  R when<R>({
+    required R Function(State data) data,
+    required R Function(Object error, StackTrace stackTrace) error,
+  }) {
+    return data(state);
+  }
+
+  @override
+  bool operator ==(Object? other) =>
+      other is ResultData<State> &&
+      other.runtimeType == runtimeType &&
+      other.state == state;
+
+  @override
+  int get hashCode => Object.hash(runtimeType, state);
+}
+
+class ResultError<State> implements Result<State> {
+  ResultError(this.error, this.stackTrace);
+
+  final Object error;
+  final StackTrace stackTrace;
+
+  @override
+  bool get hasState => false;
+
+  @override
+  State? get stateOrNull => null;
+
+  @override
+  // ignore: only_throw_errors
+  State get requireState => throw error;
+
+  @override
+  R map<R>({
+    required R Function(ResultData<State> data) data,
+    required R Function(ResultError<State>) error,
+  }) {
+    return error(this);
+  }
+
+  @override
+  R when<R>({
+    required R Function(State data) data,
+    required R Function(Object error, StackTrace stackTrace) error,
+  }) {
+    return error(this.error, stackTrace);
+  }
+
+  @override
+  bool operator ==(Object? other) =>
+      other is ResultError<State> &&
+      other.runtimeType == runtimeType &&
+      other.stackTrace == stackTrace &&
+      other.error == error;
+
+  @override
+  int get hashCode => Object.hash(runtimeType, error, stackTrace);
+}
diff --git a/packages/riverpod/lib/src/run_guarded.dart b/packages/riverpod/lib/src/run_guarded.dart
new file mode 100644
index 0000000000..d9faf5028b
--- /dev/null
+++ b/packages/riverpod/lib/src/run_guarded.dart
@@ -0,0 +1,57 @@
+import 'dart:async';
+
+/// Run a function while catching errors and reporting possible errors to the zone.
+void runGuarded(void Function() cb) {
+  try {
+    cb();
+  } catch (err, stack) {
+    Zone.current.handleUncaughtError(err, stack);
+  }
+}
+
+/// Run a function while catching errors and reporting possible errors to the zone.
+void runUnaryGuarded<T, Res>(Res Function(T) cb, T value) {
+  try {
+    cb(value);
+  } catch (err, stack) {
+    Zone.current.handleUncaughtError(err, stack);
+  }
+}
+
+/// Run a function while catching errors and reporting possible errors to the zone.
+void runBinaryGuarded<A, B>(void Function(A, B) cb, A value, B value2) {
+  try {
+    cb(value, value2);
+  } catch (err, stack) {
+    Zone.current.handleUncaughtError(err, stack);
+  }
+}
+
+/// Run a function while catching errors and reporting possible errors to the zone.
+void runTernaryGuarded<A, B, C>(
+  void Function(A, B, C) cb,
+  A value,
+  B value2,
+  C value3,
+) {
+  try {
+    cb(value, value2, value3);
+  } catch (err, stack) {
+    Zone.current.handleUncaughtError(err, stack);
+  }
+}
+
+/// Run a function while catching errors and reporting possible errors to the zone.
+void runQuaternaryGuarded<A, B, C, D>(
+  void Function(A, B, C, D) cb,
+  A value,
+  B value2,
+  C value3,
+  D value4,
+) {
+  try {
+    cb(value, value2, value3, value4);
+  } catch (err, stack) {
+    Zone.current.handleUncaughtError(err, stack);
+  }
+}
diff --git a/packages/riverpod/lib/src/state_controller.dart b/packages/riverpod/lib/src/state_controller.dart
new file mode 100644
index 0000000000..99a66abfbf
--- /dev/null
+++ b/packages/riverpod/lib/src/state_controller.dart
@@ -0,0 +1,33 @@
+import 'package:state_notifier/state_notifier.dart';
+
+/// A [StateNotifier] that allows modifying its [state] from outside.
+///
+/// This avoids having to make a [StateNotifier] subclass for simple scenarios.
+class StateController<T> extends StateNotifier<T> {
+  /// Initialize the state of [StateController].
+  StateController(T state) : super(state);
+
+  // Remove the protected status
+  @override
+  T get state => super.state;
+
+  @override
+  set state(T value) => super.state = value;
+
+  /// Calls a function with the current [state] and assigns the result as the
+  /// new state.
+  ///
+  /// This allows simplifying the syntax for updating the state when the update
+  /// depends on the previous state, such that rather than:
+  ///
+  /// ```dart
+  /// ref.read(provider.state).state = ref.read(provider.state).state + 1;
+  /// ```
+  ///
+  /// we can do:
+  ///
+  /// ```dart
+  /// ref.read(provider.state).update((state) => state + 1);
+  /// ```
+  T update(T Function(T state) cb) => state = cb(state);
+}
diff --git a/packages/riverpod/lib/src/state_notifier_provider.dart b/packages/riverpod/lib/src/state_notifier_provider.dart
index 409afe12b1..715f74aca8 100644
--- a/packages/riverpod/lib/src/state_notifier_provider.dart
+++ b/packages/riverpod/lib/src/state_notifier_provider.dart
@@ -1,32 +1,56 @@
-import 'package:meta/meta.dart';
 import 'package:state_notifier/state_notifier.dart';
 
-import 'builders.dart';
-import 'framework.dart';
-import 'future_provider.dart';
-import 'provider.dart';
-import 'value_provider.dart';
+import 'internals.dart';
 
 part 'state_notifier_provider/auto_dispose.dart';
 part 'state_notifier_provider/base.dart';
 
-/// Add [overrideWithValue] to [AutoDisposeStateNotifierProvider]
-mixin StateNotifierProviderOverrideMixin<Notifier extends StateNotifier<State>,
-    State> on ProviderBase<State> {
-  ///
-  ProviderBase<Notifier> get notifier;
+ProviderElementProxy<T, NotifierT>
+    _notifier<NotifierT extends StateNotifier<T>, T>(
+  _StateNotifierProviderBase<NotifierT, T> that,
+) {
+  return ProviderElementProxy<T, NotifierT>(
+    that,
+    (element) {
+      return (element as StateNotifierProviderElement<NotifierT, T>)
+          ._notifierNotifier;
+    },
+  );
+}
+
+abstract class _StateNotifierProviderBase<NotifierT extends StateNotifier<T>, T>
+    extends ProviderBase<T> {
+  _StateNotifierProviderBase({
+    required super.name,
+    required super.from,
+    required super.argument,
+    required this.dependencies,
+    required super.cacheTime,
+    required super.disposeDelay,
+  });
 
   @override
-  late final List<ProviderOrFamily>? dependencies = [notifier];
+  final List<ProviderOrFamily>? dependencies;
+
+  /// Obtains the [StateNotifier] associated with this provider, without listening
+  /// to state changes.
+  ///
+  /// This is typically used to invoke methods on a [StateNotifier]. For example:
+  ///
+  /// ```dart
+  /// Button(
+  ///   onTap: () => ref.read(stateNotifierProvider.notifer).increment(),
+  /// )
+  /// ```
+  ///
+  /// This listenable will notify its notifiers if the [StateNotifier] instance
+  /// changes.
+  /// This may happen if the provider is refreshed or one of its dependencies
+  /// has changes.
+  ProviderListenable<NotifierT> get notifier;
+
+  NotifierT _create(covariant StateNotifierProviderElement<NotifierT, T> ref);
 
   @override
-  ProviderBase<Notifier> get originProvider => notifier;
-
-  /// {@macro riverpod.overrridewithvalue}
-  Override overrideWithValue(Notifier value) {
-    return ProviderOverride(
-      origin: notifier,
-      override: ValueProvider<Notifier>(value),
-    );
-  }
+  bool updateShouldNotify(T previousState, T newState) => true;
 }
diff --git a/packages/riverpod/lib/src/state_notifier_provider/auto_dispose.dart b/packages/riverpod/lib/src/state_notifier_provider/auto_dispose.dart
index 43db7c1246..8e374f7d9b 100644
--- a/packages/riverpod/lib/src/state_notifier_provider/auto_dispose.dart
+++ b/packages/riverpod/lib/src/state_notifier_provider/auto_dispose.dart
@@ -2,260 +2,66 @@ part of '../state_notifier_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
 abstract class AutoDisposeStateNotifierProviderRef<
-    Notifier extends StateNotifier<State>,
-    State> implements AutoDisposeRef<Notifier> {
-  /// The [StateNotifier] currently exposed by this provider.
-  ///
-  /// Cannot be accessed while creating the provider.
-  Notifier get notifier;
-}
+        NotifierT extends StateNotifier<T>,
+        T> extends StateNotifierProviderRef<NotifierT, T>
+    implements AutoDisposeRef<T> {}
 
-/// {@template riverpod.statenotifierprovider}
-/// Creates a [StateNotifier] and exposes its current state.
-///
-/// This provider is used in combination with `package:state_notifier`.
-///
-/// Combined with [StateNotifier], [StateNotifierProvider] can be used to manipulate
-/// advanced states, that would otherwise be difficult to represent with simpler
-/// providers such as [Provider] or [FutureProvider].
-///
-/// For example, you may have a todo-list, where you can add and remove
-/// and complete a todo.
-/// Using [StateNotifier], you could represent such state as:
-///
-/// ```dart
-/// class TodosNotifier extends StateNotifier<List<Todo>> {
-///   TodosNotifier(): super([]);
-///
-///   void add(Todo todo) {
-///     state = [...state, todo];
-///   }
-///
-///   void remove(String todoId) {
-///     state = [
-///       for (final todo in state)
-///         if (todo.id != todoId) todo,
-///     ];
-///   }
-///
-///   void toggle(String todoId) {
-///     state = [
-///       for (final todo in state)
-///         if (todo.id == todoId) todo.copyWith(completed: !todo.completed),
-///     ];
-///   }
-/// }
-/// ```
-///
-/// Which you can then pass to a [StateNotifierProvider] like so:
-///
-/// ```dart
-/// final todosProvider = StateNotifierProvider<TodosNotifier, List<Todo>>((ref) => TodosNotifier());
-/// ```
-///
-/// And finally, you can interact with it inside your UI:
-///
-/// ```dart
-/// Widget build(BuildContext context, WidgetRef ref) {
-///   // rebuild the widget when the todo list changes
-///   List<Todo> todos = ref.watch(todosProvider);
-///
-///   return ListView(
-///     children: [
-///       for (final todo in todos)
-///         CheckboxListTile(
-///            value: todo.completed,
-///            // When tapping on the todo, change its completed status
-///            onChanged: (value) => ref.read(todosProvider.notifier).toggle(todo.id),
-///            title: Text(todo.description),
-///         ),
-///     ],
-///   );
-/// }
-/// ```
-/// {@endtemplate}
-@sealed
-class AutoDisposeStateNotifierProvider<Notifier extends StateNotifier<State>,
-        State> extends AutoDisposeProviderBase<State>
-    with
-        StateNotifierProviderOverrideMixin<Notifier, State>,
-        OverrideWithProviderMixin<Notifier,
-            AutoDisposeStateNotifierProvider<Notifier, State>> {
+/// {@macro riverpod.statenotifierprovider}
+class AutoDisposeStateNotifierProvider<NotifierT extends StateNotifier<T>, T>
+    extends _StateNotifierProviderBase<NotifierT, T> {
   /// {@macro riverpod.statenotifierprovider}
   AutoDisposeStateNotifierProvider(
-    Create<Notifier, AutoDisposeStateNotifierProviderRef<Notifier, State>>
-        create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Family? from,
-    Object? argument,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  })  : notifier = _AutoDisposeNotifierProvider(
-          create,
-          name: name,
-          dependencies: dependencies,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        ),
-        super(
-          name: name,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  });
 
   /// {@macro riverpod.family}
-  static const family = AutoDisposeStateNotifierProviderFamilyBuilder();
+  static const family = AutoDisposeStateNotifierProviderFamily.new;
 
-  /// {@template riverpod.statenotifierprovider.notifier}
-  /// Obtains the [StateNotifier] associated with this [AutoDisposeStateNotifierProvider],
-  /// without listening to it.
-  ///
-  /// Listening to this provider may cause providers/widgets to rebuild in the
-  /// event that the [StateNotifier] it recreated.
-  /// {@endtemplate}
-  @override
-  final AutoDisposeProviderBase<Notifier> notifier;
+  final NotifierT Function(
+      AutoDisposeStateNotifierProviderRef<NotifierT, T> ref) _createFn;
 
   @override
-  State create(AutoDisposeProviderElementBase<State> ref) {
-    final notifier = ref.watch(this.notifier);
-
-    void listener(State newState) {
-      ref.setState(newState);
-    }
-
-    final removeListener = notifier.addListener(listener);
-    ref.onDispose(removeListener);
-
-    return ref.requireState;
+  NotifierT _create(AutoDisposeStateNotifierProviderElement<NotifierT, T> ref) {
+    return _createFn(ref);
   }
 
   @override
-  bool updateShouldNotify(State previousState, State newState) {
-    return true;
+  AutoDisposeStateNotifierProviderElement<NotifierT, T> createElement() {
+    return AutoDisposeStateNotifierProviderElement._(this);
   }
 
   @override
-  AutoDisposeProviderElementBase<State> createElement() {
-    return AutoDisposeProviderElement(this);
-  }
+  late final Refreshable<NotifierT> notifier = _notifier(this);
 }
 
-class _AutoDisposeNotifierProvider<Notifier extends StateNotifier<State>, State>
-    extends AutoDisposeProviderBase<Notifier> {
-  _AutoDisposeNotifierProvider(
-    this._create, {
-    required String? name,
-    required this.dependencies,
-    Family? from,
-    Object? argument,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name == null ? null : '$name.notifier',
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final Create<Notifier, AutoDisposeStateNotifierProviderRef<Notifier, State>>
-      _create;
-
-  @override
-  final List<ProviderOrFamily>? dependencies;
-
-  @override
-  Notifier create(
-    covariant AutoDisposeStateNotifierProviderRef<Notifier, State> ref,
-  ) {
-    final notifier = _create(ref);
-    ref.onDispose(notifier.dispose);
-    return notifier;
-  }
-
-  @override
-  bool updateShouldNotify(Notifier previousState, Notifier newState) {
-    return true;
-  }
-
-  @override
-  _AutoDisposeNotifierProviderElement<Notifier, State> createElement() {
-    return _AutoDisposeNotifierProviderElement(this);
-  }
-}
-
-class _AutoDisposeNotifierProviderElement<Notifier extends StateNotifier<State>,
-        State> extends AutoDisposeProviderElementBase<Notifier>
-    implements AutoDisposeStateNotifierProviderRef<Notifier, State> {
-  _AutoDisposeNotifierProviderElement(
-    _AutoDisposeNotifierProvider<Notifier, State> provider,
-  ) : super(provider);
-
-  @override
-  Notifier get notifier => requireState;
-}
-
-/// {@template riverpod.statenotifierprovider.family}
-/// A class that allows building an [AutoDisposeStateNotifierProvider] from an external parameter.
-/// {@endtemplate}
-@sealed
-class AutoDisposeStateNotifierProviderFamily<
-        Notifier extends StateNotifier<State>, State, Arg>
-    extends Family<State, Arg,
-        AutoDisposeStateNotifierProvider<Notifier, State>> {
-  /// {@macro riverpod.statenotifierprovider.family}
+/// The element of [AutoDisposeStateNotifierProvider].
+class AutoDisposeStateNotifierProviderElement<
+        NotifierT extends StateNotifier<T>,
+        T> = StateNotifierProviderElement<NotifierT, T>
+    with AutoDisposeProviderElementMixin<T>
+    implements AutoDisposeStateNotifierProviderRef<NotifierT, T>;
+
+/// The [Family] of [AutoDisposeStateNotifierProvider].
+class AutoDisposeStateNotifierProviderFamily<NotifierT extends StateNotifier<T>,
+        T, Arg>
+    extends AutoDisposeFamilyBase<
+        AutoDisposeStateNotifierProviderRef<NotifierT, T>,
+        T,
+        Arg,
+        NotifierT,
+        AutoDisposeStateNotifierProvider<NotifierT, T>> {
+  /// The [Family] of [AutoDisposeStateNotifierProvider].
   AutoDisposeStateNotifierProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          dependencies: dependencies,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final FamilyCreate<Notifier,
-      AutoDisposeStateNotifierProviderRef<Notifier, State>, Arg> _create;
-
-  @override
-  AutoDisposeStateNotifierProvider<Notifier, State> create(Arg argument) {
-    return AutoDisposeStateNotifierProvider<Notifier, State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-      cacheTime: cacheTime,
-      disposeDelay: disposeDelay,
-    );
-  }
-
-  @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final provider = call(argument);
-    setup(origin: provider, override: provider);
-    setup(origin: provider.notifier, override: provider.notifier);
-  }
-
-  /// {@macro riverpod.overridewithprovider}
-  Override overrideWithProvider(
-    AutoDisposeStateNotifierProvider<Notifier, State> Function(Arg argument)
-        override,
-  ) {
-    return FamilyOverride<Arg>(
-      this,
-      (arg, setup) {
-        final provider = call(arg);
-        setup(origin: provider.notifier, override: override(arg).notifier);
-      },
-    );
-  }
+    super.create, {
+    super.name,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  }) : super(providerFactory: AutoDisposeStateNotifierProvider.new);
 }
diff --git a/packages/riverpod/lib/src/state_notifier_provider/base.dart b/packages/riverpod/lib/src/state_notifier_provider/base.dart
index 24cce34d21..6bbbde7664 100644
--- a/packages/riverpod/lib/src/state_notifier_provider/base.dart
+++ b/packages/riverpod/lib/src/state_notifier_provider/base.dart
@@ -1,170 +1,176 @@
 part of '../state_notifier_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
-abstract class StateNotifierProviderRef<Notifier extends StateNotifier<State>,
-    State> implements Ref<Notifier> {
+abstract class StateNotifierProviderRef<NotifierT extends StateNotifier<T>, T>
+    implements Ref<T> {
   /// The [StateNotifier] currently exposed by this provider.
   ///
   /// Cannot be accessed while creating the provider.
-  Notifier get notifier;
+  NotifierT get notifier;
 }
 
-/// {@macro riverpod.statenotifierprovider}
-@sealed
-class StateNotifierProvider<Notifier extends StateNotifier<State>, State>
-    extends AlwaysAliveProviderBase<State>
-    with
-        StateNotifierProviderOverrideMixin<Notifier, State>,
-        OverrideWithProviderMixin<Notifier,
-            StateNotifierProvider<Notifier, State>> {
+/// {@template riverpod.statenotifierprovider}
+/// Creates a [StateNotifier] and exposes its current state.
+///
+/// This provider is used in combination with `package:state_notifier`.
+///
+/// Combined with [StateNotifier], [StateNotifierProvider] can be used to manipulate
+/// advanced states, that would otherwise be difficult to represent with simpler
+/// providers such as [Provider] or [FutureProvider].
+///
+/// For example, you may have a todo-list, where you can add and remove
+/// and complete a todo.
+/// Using [StateNotifier], you could represent such state as:
+///
+/// ```dart
+/// class TodosNotifier extends StateNotifier<List<Todo>> {
+///   TodosNotifier(): super([]);
+///
+///   void add(Todo todo) {
+///     state = [...state, todo];
+///   }
+///
+///   void remove(String todoId) {
+///     state = [
+///       for (final todo in state)
+///         if (todo.id != todoId) todo,
+///     ];
+///   }
+///
+///   void toggle(String todoId) {
+///     state = [
+///       for (final todo in state)
+///         if (todo.id == todoId) todo.copyWith(completed: !todo.completed),
+///     ];
+///   }
+/// }
+/// ```
+///
+/// Which you can then pass to a [StateNotifierProvider] like so:
+///
+/// ```dart
+/// final todosProvider = StateNotifierProvider<TodosNotifier, List<Todo>>((ref) => TodosNotifier());
+/// ```
+///
+/// And finally, you can interact with it inside your UI:
+///
+/// ```dart
+/// Widget build(BuildContext context, WidgetRef ref) {
+///   // rebuild the widget when the todo list changes
+///   List<Todo> todos = ref.watch(todosProvider);
+///
+///   return ListView(
+///     children: [
+///       for (final todo in todos)
+///         CheckboxListTile(
+///            value: todo.completed,
+///            // When tapping on the todo, change its completed status
+///            onChanged: (value) => ref.read(todosProvider.notifier).toggle(todo.id),
+///            title: Text(todo.description),
+///         ),
+///     ],
+///   );
+/// }
+/// ```
+/// {@endtemplate}
+class StateNotifierProvider<NotifierT extends StateNotifier<T>, T>
+    extends _StateNotifierProviderBase<NotifierT, T>
+    with AlwaysAliveProviderBase<T> {
   /// {@macro riverpod.statenotifierprovider}
   StateNotifierProvider(
-    Create<Notifier, StateNotifierProviderRef<Notifier, State>> create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Family? from,
-    Object? argument,
-  })  : notifier = _NotifierProvider(
-          create,
-          name: name,
-          dependencies: dependencies,
-          from: from,
-          argument: argument,
-        ),
-        super(name: name, from: from, argument: argument);
-
-  /// {@macro riverpod.family}
-  static const family = StateNotifierProviderFamilyBuilder();
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+  }) : super(cacheTime: null, disposeDelay: null);
 
   /// {@macro riverpod.autoDispose}
   static const autoDispose = AutoDisposeStateNotifierProviderBuilder();
 
-  /// {@template riverpod.statenotifierprovider.notifier}
-  /// Obtains the [StateNotifier] associated with this [StateNotifierProvider],
-  /// without listening to it.
-  ///
-  /// Listening to this provider may cause providers/widgets to rebuild in the
-  /// event that the [StateNotifier] it recreated.
-  /// {@endtemplate}
-  @override
-  final AlwaysAliveProviderBase<Notifier> notifier;
-
-  @override
-  State create(ProviderElementBase<State> ref) {
-    final notifier = ref.watch(this.notifier);
-
-    void listener(State newState) {
-      ref.setState(newState);
-    }
+  /// {@macro riverpod.family}
+  static const family = StateNotifierProviderFamilyBuilder();
 
-    final removeListener = notifier.addListener(listener);
-    ref.onDispose(removeListener);
+  final NotifierT Function(StateNotifierProviderRef<NotifierT, T> ref)
+      _createFn;
 
-    return ref.requireState;
+  @override
+  NotifierT _create(StateNotifierProviderElement<NotifierT, T> ref) {
+    return _createFn(ref);
   }
 
   @override
-  bool updateShouldNotify(State previousState, State newState) {
-    return true;
+  StateNotifierProviderElement<NotifierT, T> createElement() {
+    return StateNotifierProviderElement._(this);
   }
 
   @override
-  ProviderElementBase<State> createElement() => ProviderElement(this);
+  late final AlwaysAliveRefreshable<NotifierT> notifier = _notifier(this);
 }
 
-class _NotifierProvider<Notifier extends StateNotifier<State>, State>
-    extends AlwaysAliveProviderBase<Notifier> {
-  _NotifierProvider(
-    this._create, {
-    required String? name,
-    required this.dependencies,
-    Family? from,
-    Object? argument,
-  }) : super(
-          name: name == null ? null : '$name.notifier',
-          from: from,
-          argument: argument,
-        );
-
-  final Create<Notifier, StateNotifierProviderRef<Notifier, State>> _create;
+/// The element of [StateNotifierProvider].
+class StateNotifierProviderElement<NotifierT extends StateNotifier<T>, T>
+    extends ProviderElementBase<T>
+    implements StateNotifierProviderRef<NotifierT, T> {
+  StateNotifierProviderElement._(
+    _StateNotifierProviderBase<NotifierT, T> provider,
+  ) : super(provider);
 
   @override
-  final List<ProviderOrFamily>? dependencies;
+  NotifierT get notifier => _notifierNotifier.value;
+  final _notifierNotifier = ProxyElementValueNotifier<NotifierT>();
 
-  @override
-  Notifier create(
-    covariant StateNotifierProviderRef<Notifier, State> ref,
-  ) {
-    final notifier = _create(ref);
-    ref.onDispose(notifier.dispose);
-    return notifier;
-  }
+  void Function()? _removeListener;
 
   @override
-  bool updateShouldNotify(Notifier previousState, Notifier newState) {
-    return true;
-  }
+  void create() {
+    final provider = this.provider as _StateNotifierProviderBase<NotifierT, T>;
 
-  @override
-  _NotifierProviderElement<Notifier, State> createElement() =>
-      _NotifierProviderElement(this);
-}
+    final notifier =
+        _notifierNotifier.result = Result.guard(() => provider._create(this));
 
-class _NotifierProviderElement<Notifier extends StateNotifier<State>, State>
-    extends ProviderElementBase<Notifier>
-    implements StateNotifierProviderRef<Notifier, State> {
-  _NotifierProviderElement(
-    _NotifierProvider<Notifier, State> provider,
-  ) : super(provider);
+    _removeListener = notifier
+        // TODO test requireState, as ref.read(p) is expected to throw if notifier creation failed
+        .requireState
+        .addListener(setState, fireImmediately: true);
+  }
 
   @override
-  Notifier get notifier => requireState;
-}
-
-/// {@template riverpod.statenotifierprovider.family}
-/// A class that allows building a [StateNotifierProvider] from an external parameter.
-/// {@endtemplate}
-@sealed
-class StateNotifierProviderFamily<Notifier extends StateNotifier<State>, State,
-    Arg> extends Family<State, Arg, StateNotifierProvider<Notifier, State>> {
-  /// {@macro riverpod.statenotifierprovider.family}
-  StateNotifierProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-  }) : super(name: name, dependencies: dependencies);
+  void runOnDispose() {
+    super.runOnDispose();
 
-  final FamilyCreate<Notifier, StateNotifierProviderRef<Notifier, State>, Arg>
-      _create;
+    _removeListener?.call();
+    _removeListener = null;
 
-  @override
-  StateNotifierProvider<Notifier, State> create(
-    Arg argument,
-  ) {
-    return StateNotifierProvider<Notifier, State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-    );
+    final notifier = _notifierNotifier.result?.stateOrNull;
+    if (notifier != null) {
+      // TODO test STateNotifier.dispose is guarded
+      runGuarded(notifier.dispose);
+    }
+    _notifierNotifier.result = null;
   }
 
   @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final provider = call(argument);
-    setup(origin: provider.notifier, override: provider.notifier);
-  }
-
-  /// {@macro riverpod.overridewithprovider}
-  Override overrideWithProvider(
-    StateNotifierProvider<Notifier, State> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(
-      this,
-      (arg, setup) {
-        final provider = call(arg);
-        setup(origin: provider.notifier, override: override(arg).notifier);
-      },
+  void visitChildren({
+    required void Function(ProviderElementBase element) elementVisitor,
+    required void Function(ProxyElementValueNotifier element) notifierVisitor,
+  }) {
+    super.visitChildren(
+      elementVisitor: elementVisitor,
+      notifierVisitor: notifierVisitor,
     );
+    notifierVisitor(_notifierNotifier);
   }
 }
+
+/// The [Family] of [StateNotifierProvider].
+class StateNotifierProviderFamily<NotifierT extends StateNotifier<T>, T, Arg>
+    extends FamilyBase<StateNotifierProviderRef<NotifierT, T>, T, Arg,
+        NotifierT, StateNotifierProvider<NotifierT, T>> {
+  /// The [Family] of [StateNotifierProvider].
+  StateNotifierProviderFamily(
+    super.create, {
+    super.name,
+    super.dependencies,
+  }) : super(providerFactory: StateNotifierProvider.new);
+}
diff --git a/packages/riverpod/lib/src/state_provider.dart b/packages/riverpod/lib/src/state_provider.dart
index 14e1a71bb1..70de8d13d5 100644
--- a/packages/riverpod/lib/src/state_provider.dart
+++ b/packages/riverpod/lib/src/state_provider.dart
@@ -1,112 +1,55 @@
-import 'package:meta/meta.dart';
-
-import '../riverpod.dart';
 import 'internals.dart';
+import 'state_controller.dart';
 
 part 'state_provider/auto_dispose.dart';
 part 'state_provider/base.dart';
 
-/// A [StateNotifier] that allows modifying its [state] from outside.
-///
-/// This avoids having to make a [StateNotifier] subclass for simple scenarios.
-class StateController<T> extends StateNotifier<T> {
-  /// Initialize the state of [StateController].
-  StateController(T state) : super(state);
-
-  // Remove the protected status
-  @override
-  T get state => super.state;
-
-  @override
-  set state(T value) => super.state = value;
-
-  /// Calls a function with the current [state] and assigns the result as the
-  /// new state.
-  ///
-  /// This allows simplifying the syntax for updating the state when the update
-  /// depends on the previous state, such that rather than:
-  ///
-  /// ```dart
-  /// ref.read(provider.state).state = ref.read(provider.state).state + 1;
-  /// ```
-  ///
-  /// we can do:
-  ///
-  /// ```dart
-  /// ref.read(provider.state).update((state) => state + 1);
-  /// ```
-  T update(T Function(T state) cb) => state = cb(state);
+ProviderElementProxy<T, StateController<T>> _notifier<T>(
+  _StateProviderBase<T> that,
+) {
+  return ProviderElementProxy<T, StateController<T>>(
+    that,
+    (element) {
+      return (element as StateProviderElement<T>)._controllerNotifier;
+    },
+  );
 }
 
-/// {@template riverpod.stateprovider}
-/// A provider that exposes a value that can be modified from outside.
-///
-/// It can be useful for very simple states, like a filter or the currently
-/// selected item – which can then be combined with other providers or accessed
-/// in multiple screens.
-///
-/// The following code shows a list of products, and allows selecting
-/// a product by tapping on it.
-///
-/// ```dart
-/// final selectedProductIdProvider = StateProvider<String?>((ref) => null);
-/// final productsProvider = StateNotifierProvider<ProductsNotifier, List<Product>>((ref) => ProductsNotifier());
-///
-/// Widget build(BuildContext context, WidgetRef ref) {
-///   final List<Product> products = ref.watch(productsProvider);
-///   final selectedProductId = ref.watch(selectedProductIdProvider);
-///
-///   return ListView(
-///     children: [
-///       for (final product in products)
-///         GestureDetector(
-///           onTap: () => ref.read(selectedProductIdProvider.notifier).state = product.id,
-///           child: ProductItem(
-///             product: product,
-///             isSelected: selectedProductId.state == product.id,
-///           ),
-///         ),
-///     ],
-///   );
-/// }
-/// ```
-/// {@endtemplate}
-StateController<State> _listenStateProvider<State>(
-  ProviderElementBase<StateController<State>> ref,
-  StateController<State> controller,
+ProviderElementProxy<T, StateController<T>> _state<T>(
+  _StateProviderBase<T> that,
 ) {
-  void listener(State newState) {
-    ref.setState(controller);
-  }
-
-  // No need to remove the listener on dispose, since we are disposing the controller
-  ref.onDispose(
-    controller.addListener(listener, fireImmediately: false),
+  return ProviderElementProxy<T, StateController<T>>(
+    that,
+    (element) {
+      if (element is StateProviderElement<T>) {
+        return element._stateNotifier;
+      }
+
+      throw UnsupportedError('Unknown element type ${element.runtimeType}');
+    },
   );
-
-  return controller;
 }
 
-/// Add [overrideWithValue] to [StateProvider]
-mixin StateProviderOverrideMixin<State> on ProviderBase<State> {
-  ///
-  ProviderBase<StateController<State>> get notifier;
-
-  /// Obtains the [StateNotifier] and also listens to the state, as opposed to
-  /// [notifier] which will not listen to the state.
-  ProviderBase<StateController<State>> get state;
+abstract class _StateProviderBase<T> extends ProviderBase<T> {
+  _StateProviderBase({
+    required super.name,
+    required super.from,
+    required super.argument,
+    required this.dependencies,
+    required super.cacheTime,
+    required super.disposeDelay,
+  });
 
   @override
-  late final List<ProviderOrFamily>? dependencies = [notifier];
+  final List<ProviderOrFamily>? dependencies;
 
-  @override
-  ProviderBase<StateController<State>> get originProvider => notifier;
+  ProviderListenable<StateController<T>> get notifier;
+  ProviderListenable<StateController<T>> get state;
+
+  T _create(covariant StateProviderElement<T> ref);
 
-  /// {@macro riverpod.overrridewithvalue}
-  Override overrideWithValue(StateController<State> value) {
-    return ProviderOverride(
-      origin: notifier,
-      override: ValueProvider<StateController<State>>(value),
-    );
+  @override
+  bool updateShouldNotify(T previousState, T newState) {
+    return true;
   }
 }
diff --git a/packages/riverpod/lib/src/state_provider/auto_dispose.dart b/packages/riverpod/lib/src/state_provider/auto_dispose.dart
index e98b121ec1..66c56665ae 100644
--- a/packages/riverpod/lib/src/state_provider/auto_dispose.dart
+++ b/packages/riverpod/lib/src/state_provider/auto_dispose.dart
@@ -3,215 +3,55 @@ part of '../state_provider.dart';
 /// {@macro riverpod.providerrefbase}
 /// - [controller], the [StateController] currently exposed by this provider.
 abstract class AutoDisposeStateProviderRef<State>
-    implements
-        AutoDisposeRef<StateController<State>>,
-        StateProviderRef<State> {}
+    extends StateProviderRef<State> implements AutoDisposeRef<State> {}
 
 /// {@macro riverpod.stateprovider}
-@sealed
-class AutoDisposeStateProvider<State> extends AutoDisposeProviderBase<State>
-    with
-        StateProviderOverrideMixin<State>,
-        OverrideWithProviderMixin<StateController<State>,
-            AutoDisposeStateProvider<State>> {
+class AutoDisposeStateProvider<T> extends _StateProviderBase<T> {
   /// {@macro riverpod.stateprovider}
   AutoDisposeStateProvider(
-    Create<State, AutoDisposeStateProviderRef<State>> create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Family? from,
-    Object? argument,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  })  : notifier = _AutoDisposeNotifierProvider(
-          create,
-          name: modifierName(name, 'notifier'),
-          dependencies: dependencies,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        ),
-        super(
-          name: name,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  });
 
   /// {@macro riverpod.family}
-  static const family = AutoDisposeStateProviderFamilyBuilder();
+  static const family = AutoDisposeStateProviderFamily.new;
 
-  /// {@macro riverpod.stateprovider.notifier}
-  @override
-  final AutoDisposeProviderBase<StateController<State>> notifier;
+  final T Function(AutoDisposeStateProviderRef<T> ref) _createFn;
 
   @override
-  late final AutoDisposeProviderBase<StateController<State>> state =
-      _AutoDisposeNotifierStateProvider(
-    (ref) {
-      return _listenStateProvider(
-        ref as ProviderElementBase<StateController<State>>,
-        ref.watch(notifier),
-      );
-    },
-    dependencies: [notifier],
-    from: from,
-    argument: argument,
-    name: modifierName(name, 'state'),
-  );
+  T _create(AutoDisposeStateProviderElement<T> ref) => _createFn(ref);
 
   @override
-  State create(AutoDisposeProviderElementBase<State> ref) {
-    final notifier = ref.watch(this.notifier);
-
-    final removeListener = notifier.addListener(ref.setState);
-    ref.onDispose(removeListener);
-
-    return notifier.state;
+  AutoDisposeStateProviderElement<T> createElement() {
+    return AutoDisposeStateProviderElement._(this);
   }
 
   @override
-  bool updateShouldNotify(State previousState, State newState) {
-    return true;
-  }
+  late final Refreshable<StateController<T>> notifier = _notifier(this);
 
   @override
-  AutoDisposeStateProviderElement<State> createElement() {
-    return AutoDisposeStateProviderElement(this);
-  }
+  late final Refreshable<StateController<T>> state = _state(this);
 }
 
-/// The [ProviderElementBase] for [StateProvider]
-class AutoDisposeStateProviderElement<State>
-    extends AutoDisposeProviderElementBase<State> {
-  /// The [ProviderElementBase] for [StateProvider]
-  AutoDisposeStateProviderElement(AutoDisposeStateProvider<State> provider)
-      : super(provider);
-}
-
-class _AutoDisposeNotifierProvider<State>
-    extends AutoDisposeProviderBase<StateController<State>> {
-  _AutoDisposeNotifierProvider(
-    this._create, {
-    required String? name,
-    required this.dependencies,
-    required Family? from,
-    required Object? argument,
-    required Duration? cacheTime,
-    required Duration? disposeDelay,
-  }) : super(
-          name: name,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final Create<State, AutoDisposeStateProviderRef<State>> _create;
-
-  @override
-  final List<ProviderOrFamily>? dependencies;
-
-  @override
-  StateController<State> create(AutoDisposeStateProviderRef<State> ref) {
-    final initialState = _create(ref);
-    final notifier = StateController(initialState);
-    ref.onDispose(notifier.dispose);
-    return notifier;
-  }
-
-  @override
-  bool updateShouldNotify(
-    StateController<State> previousState,
-    StateController<State> newState,
-  ) {
-    return true;
-  }
-
-  @override
-  _AutoDisposeNotifierStateProviderElement<State> createElement() {
-    return _AutoDisposeNotifierStateProviderElement(this);
-  }
-}
+/// The element of [StateProvider].
+class AutoDisposeStateProviderElement<T> = StateProviderElement<T>
+    with AutoDisposeProviderElementMixin<T>
+    implements AutoDisposeStateProviderRef<T>;
 
-class _AutoDisposeNotifierStateProviderElement<State>
-    extends AutoDisposeProviderElementBase<StateController<State>>
-    implements AutoDisposeStateProviderRef<State> {
-  _AutoDisposeNotifierStateProviderElement(
-      _AutoDisposeNotifierProvider<State> provider)
-      : super(provider);
-
-  @override
-  StateController<State> get controller => requireState;
-}
-
-class _AutoDisposeNotifierStateProvider<State>
-    extends AutoDisposeProvider<State> {
-  _AutoDisposeNotifierStateProvider(
-    Create<State, AutoDisposeProviderRef<State>> create, {
-    super.dependencies,
-    required super.from,
-    required super.argument,
-    required super.name,
-  }) : super(create);
-
-  @override
-  bool updateShouldNotify(State previousState, State newState) {
-    return true;
-  }
-}
-
-/// {@macro riverpod.stateprovider.family}
-@sealed
-class AutoDisposeStateProviderFamily<State, Arg>
-    extends Family<State, Arg, AutoDisposeStateProvider<State>> {
-  /// {@macro riverpod.stateprovider.family}
+/// The [Family] of [StateProvider].
+class AutoDisposeStateProviderFamily<R, Arg> extends AutoDisposeFamilyBase<
+    AutoDisposeStateProviderRef<R>, R, Arg, R, AutoDisposeStateProvider<R>> {
+  /// The [Family] of [StateProvider].
   AutoDisposeStateProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          dependencies: dependencies,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final FamilyCreate<State, AutoDisposeStateProviderRef<State>, Arg> _create;
-
-  @override
-  AutoDisposeStateProvider<State> create(Arg argument) {
-    return AutoDisposeStateProvider<State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-      cacheTime: cacheTime,
-      disposeDelay: disposeDelay,
-    );
-  }
-
-  @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final provider = call(argument);
-    setup(origin: provider.notifier, override: provider.notifier);
-  }
-
-  /// {@macro riverpod.overridewithprovider}
-  Override overrideWithProvider(
-    AutoDisposeStateProvider<State> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(
-      this,
-      (arg, setup) {
-        final provider = call(arg);
-        final newProvider = override(arg);
-        setup(origin: provider.notifier, override: newProvider.notifier);
-      },
-    );
-  }
+    super.create, {
+    super.name,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  }) : super(providerFactory: AutoDisposeStateProvider.new);
 }
diff --git a/packages/riverpod/lib/src/state_provider/base.dart b/packages/riverpod/lib/src/state_provider/base.dart
index d09bb7fa7c..96dbb54b8a 100644
--- a/packages/riverpod/lib/src/state_provider/base.dart
+++ b/packages/riverpod/lib/src/state_provider/base.dart
@@ -2,215 +2,138 @@ part of '../state_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
 /// - [controller], the [StateController] currently exposed by this provider.
-abstract class StateProviderRef<State> implements Ref<StateController<State>> {
+abstract class StateProviderRef<State> implements Ref<State> {
   /// The [StateController] currently exposed by this provider.
   ///
   /// Cannot be accessed while creating the provider.
   StateController<State> get controller;
 }
 
-/// {@macro riverpod.stateprovider}
-@sealed
-class StateProvider<State> extends AlwaysAliveProviderBase<State>
-    with
-        StateProviderOverrideMixin<State>,
-        OverrideWithProviderMixin<StateController<State>,
-            StateProvider<State>> {
+/// {@template riverpod.stateprovider}
+/// A provider that exposes a value that can be modified from outside.
+///
+/// It can be useful for very simple states, like a filter or the currently
+/// selected item – which can then be combined with other providers or accessed
+/// in multiple screens.
+///
+/// The following code shows a list of products, and allows selecting
+/// a product by tapping on it.
+///
+/// ```dart
+/// final selectedProductIdProvider = StateProvider<String?>((ref) => null);
+/// final productsProvider = StateNotifierProvider<ProductsNotifier, List<Product>>((ref) => ProductsNotifier());
+///
+/// Widget build(BuildContext context, WidgetRef ref) {
+///   final List<Product> products = ref.watch(productsProvider);
+///   final selectedProductId = ref.watch(selectedProductIdProvider);
+///
+///   return ListView(
+///     children: [
+///       for (final product in products)
+///         GestureDetector(
+///           onTap: () => ref.read(selectedProductIdProvider.notifier).state = product.id,
+///           child: ProductItem(
+///             product: product,
+///             isSelected: selectedProductId.state == product.id,
+///           ),
+///         ),
+///     ],
+///   );
+/// }
+/// ```
+/// {@endtemplate}
+class StateProvider<T> extends _StateProviderBase<T>
+    with AlwaysAliveProviderBase<T> {
   /// {@macro riverpod.stateprovider}
   StateProvider(
-    Create<State, StateProviderRef<State>> create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Family? from,
-    Object? argument,
-  })  : notifier = _NotifierProvider(
-          create,
-          name: modifierName(name, 'notifier'),
-          dependencies: dependencies,
-          from: from,
-          argument: argument,
-        ),
-        super(name: name, from: from, argument: argument);
-
-  /// {@macro riverpod.family}
-  static const family = StateProviderFamilyBuilder();
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+  }) : super(cacheTime: null, disposeDelay: null);
 
   /// {@macro riverpod.autoDispose}
   static const autoDispose = AutoDisposeStateProviderBuilder();
 
-  @override
-  ProviderBase<StateController<State>> get originProvider => notifier;
+  /// {@macro riverpod.family}
+  static const family = StateProviderFamilyBuilder();
 
-  @override
-  late final AlwaysAliveProviderBase<StateController<State>> state =
-      _NotifierStateProvider(
-    (ref) {
-      return _listenStateProvider(
-        ref as ProviderElementBase<StateController<State>>,
-        ref.watch(notifier),
-      );
-    },
-    dependencies: [notifier],
-    from: from,
-    argument: argument,
-    name: modifierName(name, 'state'),
-  );
-
-  /// {@template riverpod.stateprovider.notifier}
-  /// Obtains the [StateController] associated with this provider, but without
-  /// listening to it.
-  ///
-  /// Listening to this provider may cause providers/widgets to rebuild in the
-  /// event that the [StateController] it recreated.
-  ///
-  ///
-  /// It is preferable to do:
-  /// ```dart
-  /// ref.watch(stateProvider.notifier)
-  /// ```
-  ///
-  /// instead of:
-  /// ```dart
-  /// ref.read(stateProvider)
-  /// ```
-  ///
-  /// The reasoning is, using `read` could cause hard to catch bugs, such as
-  /// not rebuilding dependent providers/widgets after using `ref.refresh` on this provider.
-  /// {@endtemplate}
-  @override
-  final AlwaysAliveProviderBase<StateController<State>> notifier;
+  final T Function(StateProviderRef<T> ref) _createFn;
 
   @override
-  State create(
-    ProviderElementBase<State> ref,
-  ) {
-    final notifier = ref.watch(this.notifier);
-
-    final removeListener = notifier.addListener(ref.setState);
-    ref.onDispose(removeListener);
-
-    return notifier.state;
-  }
+  T _create(StateProviderElement<T> ref) => _createFn(ref);
 
   @override
-  bool updateShouldNotify(State previousState, State newState) {
-    return true;
-  }
+  StateProviderElement<T> createElement() => StateProviderElement._(this);
 
   @override
-  StateProviderElement<State> createElement() => StateProviderElement(this);
-}
+  late final AlwaysAliveRefreshable<StateController<T>> notifier =
+      _notifier(this);
 
-/// The [ProviderElementBase] for [StateProvider]
-class StateProviderElement<State> extends ProviderElementBase<State> {
-  /// The [ProviderElementBase] for [StateProvider]
-  StateProviderElement(StateProvider<State> provider) : super(provider);
+  @override
+  late final AlwaysAliveRefreshable<StateController<T>> state = _state(this);
 }
 
-class _NotifierStateProvider<State> extends Provider<State> {
-  _NotifierStateProvider(
-    Create<State, ProviderRef<State>> create, {
-    super.dependencies,
-    required super.from,
-    required super.argument,
-    required super.name,
-  }) : super(create);
+/// The element of [StateProvider].
+class StateProviderElement<T> extends ProviderElementBase<T>
+    implements StateProviderRef<T> {
+  StateProviderElement._(_StateProviderBase<T> provider) : super(provider);
 
   @override
-  bool updateShouldNotify(State previousState, State newState) {
-    return true;
-  }
-}
+  StateController<T> get controller => _controllerNotifier.value;
+  final _controllerNotifier = ProxyElementValueNotifier<StateController<T>>();
 
-class _NotifierProvider<State>
-    extends AlwaysAliveProviderBase<StateController<State>> {
-  _NotifierProvider(
-    this._create, {
-    required String? name,
-    required this.dependencies,
-    required Family? from,
-    required Object? argument,
-  }) : super(name: name, from: from, argument: argument);
+  final _stateNotifier = ProxyElementValueNotifier<StateController<T>>();
 
-  final Create<State, StateProviderRef<State>> _create;
+  void Function()? _removeListener;
 
   @override
-  final List<ProviderOrFamily>? dependencies;
+  void create() {
+    final provider = this.provider as _StateProviderBase<T>;
+    final initialState = provider._create(this);
 
-  @override
-  StateController<State> create(StateProviderRef<State> ref) {
-    final initialState = _create(ref);
-    final notifier = StateController(initialState);
-    ref.onDispose(notifier.dispose);
-    return notifier;
-  }
+    final controller = StateController(initialState);
+    _controllerNotifier.result = Result.data(controller);
 
-  @override
-  bool updateShouldNotify(
-    StateController<State> previousState,
-    StateController<State> newState,
-  ) {
-    return true;
+    _removeListener = controller.addListener((state) {
+      _stateNotifier.result = _controllerNotifier.result;
+      setState(state);
+    }, fireImmediately: true);
   }
 
   @override
-  _NotifierStateProviderElement<State> createElement() {
-    return _NotifierStateProviderElement(this);
-  }
-}
+  void runOnDispose() {
+    super.runOnDispose();
 
-class _NotifierStateProviderElement<State>
-    extends ProviderElementBase<StateController<State>>
-    implements StateProviderRef<State> {
-  _NotifierStateProviderElement(_NotifierProvider<State> provider)
-      : super(provider);
+    _removeListener?.call();
+    _removeListener = null;
 
-  @override
-  StateController<State> get controller => requireState;
-}
-
-/// {@macro riverpod.stateprovider.family}
-@sealed
-class StateProviderFamily<State, Arg>
-    extends Family<State, Arg, StateProvider<State>> {
-  /// {@macro riverpod.stateprovider.family}
-  StateProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-  }) : super(name: name, dependencies: dependencies);
-
-  final FamilyCreate<State, StateProviderRef<State>, Arg> _create;
-
-  @override
-  StateProvider<State> create(
-    Arg argument,
-  ) {
-    return StateProvider<State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-    );
+    _controllerNotifier.result?.stateOrNull?.dispose();
+    _controllerNotifier.result = null;
   }
 
   @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final provider = call(argument);
-    setup(origin: provider.notifier, override: provider.notifier);
-  }
-
-  /// {@macro riverpod.overidewithprovider}
-  Override overrideWithProvider(
-    StateProvider<State> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(
-      this,
-      (arg, setup) {
-        final provider = call(arg);
-        final newProvider = override(arg);
-        setup(origin: provider.notifier, override: newProvider.notifier);
-      },
+  void visitChildren({
+    required void Function(ProviderElementBase element) elementVisitor,
+    required void Function(ProxyElementValueNotifier element) notifierVisitor,
+  }) {
+    super.visitChildren(
+      elementVisitor: elementVisitor,
+      notifierVisitor: notifierVisitor,
     );
+    notifierVisitor(_stateNotifier);
+    notifierVisitor(_controllerNotifier);
   }
 }
+
+/// The [Family] of [StateProvider].
+class StateProviderFamily<R, Arg>
+    extends FamilyBase<StateProviderRef<R>, R, Arg, R, StateProvider<R>> {
+  /// The [Family] of [StateProvider].
+  StateProviderFamily(
+    super.create, {
+    super.name,
+    super.dependencies,
+  }) : super(providerFactory: StateProvider.new);
+}
diff --git a/packages/riverpod/lib/src/stream_provider.dart b/packages/riverpod/lib/src/stream_provider.dart
index aba458562e..3f28c3d0f6 100644
--- a/packages/riverpod/lib/src/stream_provider.dart
+++ b/packages/riverpod/lib/src/stream_provider.dart
@@ -1,91 +1,62 @@
 import 'dart:async';
 
-import 'package:meta/meta.dart';
-
-import 'async_value_converters.dart';
 import 'builders.dart';
 import 'common.dart';
 import 'framework.dart';
-import 'future_provider.dart';
-import 'provider.dart';
+import 'future_provider.dart' show FutureProvider;
+import 'listenable.dart';
+import 'provider.dart' show Provider;
+import 'result.dart';
+import 'synchronous_future.dart';
 
 part 'stream_provider/auto_dispose.dart';
 part 'stream_provider/base.dart';
 
-/// {@template riverpod.streamprovider}
-/// Creates a stream and exposes its latest event.
-///
-/// [StreamProvider] is identical in behavior/usage to [FutureProvider], modulo
-/// the fact that the value created is a [Stream] instead of a [Future].
-///
-/// It can be used to express a value asynchronously loaded that can change over
-/// time, such as an editable `Message` coming from a web socket:
-///
-/// ```dart
-/// final messageProvider = StreamProvider.autoDispose<String>((ref) async* {
-///   // Open the connection
-///   final channel = IOWebSocketChannel.connect('ws://echo.websocket.org');
-///
-///   // Close the connection when the stream is destroyed
-///   ref.onDispose(() => channel.sink.close());
-///
-///   // Parse the value received and emit a Message instance
-///   await for (final value in channel.stream) {
-///     yield value.toString();
-///   }
-/// });
-/// ```
-///
-/// Which the UI can then listen:
-///
-/// ```dart
-/// Widget build(BuildContext context, WidgetRef ref) {
-///   AsyncValue<String> message = ref.watch(messageProvider);
-///
-///   return message.when(
-///     loading: () => const CircularProgressIndicator(),
-///     error: (err, stack) => Text('Error: $err'),
-///     data: (message) {
-///       return Text(message);
-///     },
-///   );
-/// }
-/// ```
-///
-/// **Note**:
-/// When listening to web sockets, firebase, or anything that consumes resources,
-/// it is important to use [StreamProvider.autoDispose] instead of simply [StreamProvider].
-///
-/// This ensures that the resources are released when no longer needed as,
-/// by default, a [StreamProvider] is almost never destroyed.
-///
-/// See also:
-///
-/// - [Provider], a provider that synchronously creates a value
-/// - [FutureProvider], a provider that asynchronously exposes a value that
-///   can change over time.
-/// - [AlwaysAliveAsyncProviderX.stream], to obtain the [Stream] created instead of an [AsyncValue].
-/// - [AlwaysAliveAsyncProviderX.future], to obtain the last value emitted by a [Stream].
-/// - [StreamProvider.family], to create a [StreamProvider] from external parameters
-/// - [StreamProvider.autoDispose], to destroy the state of a [StreamProvider] when no longer needed.
-/// {@endtemplate}
-mixin _StreamProviderElementMixin<State>
-    on ProviderElementBase<AsyncValue<State>> {
-  AsyncValue<State> _listenStream(Stream<State> Function() stream) {
-    try {
-      final sub = stream().listen(
-        (event) => setState(AsyncValue.data(event)),
-        // ignore: avoid_types_on_closure_parameters
-        onError: (Object err, StackTrace stack) {
-          setState(AsyncValue.error(err, stackTrace: stack));
-        },
-      );
+ProviderElementProxy<AsyncValue<T>, Future<T>> _future<T>(
+  _StreamProviderBase<T> that,
+) {
+  return ProviderElementProxy<AsyncValue<T>, Future<T>>(
+    that,
+    (element) => (element as StreamProviderElement<T>)._futureNotifier,
+  );
+}
+
+ProviderElementProxy<AsyncValue<T>, Stream<T>> _stream<T>(
+  _StreamProviderBase<T> that,
+) {
+  return ProviderElementProxy<AsyncValue<T>, Stream<T>>(
+    that,
+    (element) {
+      return (element as StreamProviderElement<T>)._streamNotifier;
+    },
+  );
+}
+
+abstract class _StreamProviderBase<T> extends ProviderBase<AsyncValue<T>> {
+  _StreamProviderBase({
+    required this.dependencies,
+    required super.name,
+    required super.from,
+    required super.argument,
+    required super.cacheTime,
+    required super.disposeDelay,
+  });
+
+  @override
+  final List<ProviderOrFamily>? dependencies;
+
+  ProviderListenable<Future<T>> get future;
+  ProviderListenable<Stream<T>> get stream;
+
+  Stream<T> _create(covariant StreamProviderElement<T> ref);
+
+  @override
+  bool updateShouldNotify(AsyncValue<T> previousState, AsyncValue<T> newState) {
+    final wasLoading = previousState is AsyncLoading;
+    final isLoading = newState is AsyncLoading;
 
-      onDispose(sub.cancel);
+    if (wasLoading || isLoading) return wasLoading != isLoading;
 
-      return AsyncValue<State>.loading();
-    } catch (err, stack) {
-      return AsyncValue<State>.error(err, stackTrace: stack);
-    }
+    return true;
   }
 }
diff --git a/packages/riverpod/lib/src/stream_provider/auto_dispose.dart b/packages/riverpod/lib/src/stream_provider/auto_dispose.dart
index 1f39d527e2..6799f91487 100644
--- a/packages/riverpod/lib/src/stream_provider/auto_dispose.dart
+++ b/packages/riverpod/lib/src/stream_provider/auto_dispose.dart
@@ -1,168 +1,62 @@
 part of '../stream_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
-/// - [ProviderRef.state], the value currently exposed by this provider.
 abstract class AutoDisposeStreamProviderRef<State>
-    implements AutoDisposeRef<AsyncValue<State>> {
-  /// Obtains the state currently exposed by this provider.
-  ///
-  /// Mutating this property will notify the provider listeners.
-  ///
-  /// Cannot be called while a provider is creating, unless the setter was called first.
-  ///
-  /// Will throw if the provider threw during creation.
-  AsyncValue<State> get state;
-  set state(AsyncValue<State> newState);
-}
+    extends StreamProviderRef<State>
+    implements AutoDisposeRef<AsyncValue<State>> {}
 
 /// {@macro riverpod.streamprovider}
-@sealed
-class AutoDisposeStreamProvider<State>
-    extends AutoDisposeProviderBase<AsyncValue<State>>
-    with
-        OverrideWithValueMixin<AsyncValue<State>>,
-        OverrideWithProviderMixin<AsyncValue<State>,
-            AutoDisposeProviderBase<AsyncValue<State>>> {
+class AutoDisposeStreamProvider<T> extends _StreamProviderBase<T>
+    with AsyncSelector<T> {
   /// {@macro riverpod.streamprovider}
   AutoDisposeStreamProvider(
-    this._create, {
-    String? name,
-    this.dependencies,
-    Family? from,
-    Object? argument,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          from: from,
-          argument: argument,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  });
 
   /// {@macro riverpod.family}
-  static const family = AutoDisposeStreamProviderFamilyBuilder();
-
-  @override
-  ProviderBase<AsyncValue<State>> get originProvider => this;
+  static const family = AutoDisposeStreamProviderFamily.new;
 
-  final Create<Stream<State>, AutoDisposeStreamProviderRef<State>> _create;
+  final Stream<T> Function(AutoDisposeStreamProviderRef<T> ref) _createFn;
 
   @override
-  final List<ProviderOrFamily>? dependencies;
-
-  /// {@template riverpod.streamprovider.stream}
-  late final AutoDisposeProviderBase<Stream<State>> stream =
-      AutoDisposeAsyncValueAsStreamProvider(
-    this,
-    from: from,
-    argument: argument,
-    cacheTime: cacheTime,
-    disposeDelay: disposeDelay,
-  );
-
-  /// {@template riverpod.streamprovider.future}
-  late final AutoDisposeProviderBase<Future<State>> future =
-      AutoDisposeAsyncValueAsFutureProvider(
-    this,
-    from: from,
-    argument: argument,
-    cacheTime: cacheTime,
-    disposeDelay: disposeDelay,
-  );
-
-  /// {@template riverpod.streamprovider.future}
-  @Deprecated('Use `future` instead')
-  AutoDisposeProviderBase<Future<State>> get last => future;
+  Stream<T> _create(AutoDisposeStreamProviderElement<T> ref) => _createFn(ref);
 
   @override
-  AsyncValue<State> create(
-    covariant AutoDisposeStreamProviderElement<State> ref,
-  ) {
-    return ref._listenStream(() => _create(ref));
+  AutoDisposeStreamProviderElement<T> createElement() {
+    return AutoDisposeStreamProviderElement._(this);
   }
 
   @override
-  bool updateShouldNotify(
-    AsyncValue<State> previousState,
-    AsyncValue<State> newState,
-  ) {
-    final wasLoading = previousState is AsyncLoading;
-    final isLoading = newState is AsyncLoading;
-
-    if (wasLoading || isLoading) return wasLoading != isLoading;
-
-    return true;
-  }
+  late final Refreshable<Future<T>> future = _future(this);
 
   @override
-  AutoDisposeStreamProviderElement<State> createElement() {
-    return AutoDisposeStreamProviderElement(this);
-  }
+  late final Refreshable<Stream<T>> stream = _stream(this);
 }
 
-/// The Element of an [AutoDisposeStreamProvider]
-class AutoDisposeStreamProviderElement<State>
-    extends AutoDisposeProviderElementBase<AsyncValue<State>>
-    with _StreamProviderElementMixin<State>
-    implements AutoDisposeStreamProviderRef<State> {
-  /// The Element of an [AutoDisposeStreamProvider]
-  AutoDisposeStreamProviderElement(AutoDisposeStreamProvider<State> provider)
-      : super(provider);
-
-  @override
-  AsyncValue<State> get state => requireState;
-
-  @override
-  set state(AsyncValue<State> newState) => setState(newState);
-}
-
-/// {@macro riverpod.streamprovider.family}
-@sealed
-class AutoDisposeStreamProviderFamily<State, Arg>
-    extends Family<AsyncValue<State>, Arg, AutoDisposeStreamProvider<State>> {
-  /// {@macro riverpod.streamprovider.family}
+/// The element of [AutoDisposeStreamProvider].
+class AutoDisposeStreamProviderElement<T> = StreamProviderElement<T>
+    with AutoDisposeProviderElementMixin<AsyncValue<T>>
+    implements AutoDisposeStreamProviderRef<T>;
+
+/// The [Family] of [AutoDisposeStreamProvider].
+class AutoDisposeStreamProviderFamily<R, Arg> extends AutoDisposeFamilyBase<
+    AutoDisposeStreamProviderRef<R>,
+    AsyncValue<R>,
+    Arg,
+    Stream<R>,
+    AutoDisposeStreamProvider<R>> {
+  /// The [Family] of [AutoDisposeStreamProvider].
   AutoDisposeStreamProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-    Duration? cacheTime,
-    Duration? disposeDelay,
-  }) : super(
-          name: name,
-          dependencies: dependencies,
-          cacheTime: cacheTime,
-          disposeDelay: disposeDelay,
-        );
-
-  final FamilyCreate<Stream<State>, AutoDisposeStreamProviderRef<State>, Arg>
-      _create;
-
-  @override
-  AutoDisposeStreamProvider<State> create(Arg argument) {
-    return AutoDisposeStreamProvider<State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
-      cacheTime: cacheTime,
-      disposeDelay: disposeDelay,
-    );
-  }
-
-  @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final provider = call(argument);
-    setup(origin: provider, override: provider);
-  }
-
-  /// {@macro riverpod.overridewithprovider}
-  Override overrideWithProvider(
-    AutoDisposeProviderBase<AsyncValue<State>> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(this, (arg, setup) {
-      final provider = call(arg);
-      setup(origin: provider, override: override(arg));
-    });
-  }
+    super.create, {
+    super.name,
+    super.dependencies,
+    super.cacheTime,
+    super.disposeDelay,
+  }) : super(providerFactory: AutoDisposeStreamProvider.new);
 }
diff --git a/packages/riverpod/lib/src/stream_provider/base.dart b/packages/riverpod/lib/src/stream_provider/base.dart
index 5bc7bffa65..957d86cb1d 100644
--- a/packages/riverpod/lib/src/stream_provider/base.dart
+++ b/packages/riverpod/lib/src/stream_provider/base.dart
@@ -1,7 +1,7 @@
 part of '../stream_provider.dart';
 
 /// {@macro riverpod.providerrefbase}
-/// - [ProviderRef.state], the value currently exposed by this provider.
+/// - [StreamProviderRef.state], the value currently exposed by this provider.
 abstract class StreamProviderRef<State> implements Ref<AsyncValue<State>> {
   /// Obtains the state currently exposed by this provider.
   ///
@@ -14,233 +14,227 @@ abstract class StreamProviderRef<State> implements Ref<AsyncValue<State>> {
   set state(AsyncValue<State> newState);
 }
 
-/// {@macro riverpod.streamprovider}
-@sealed
-class StreamProvider<State> extends AlwaysAliveProviderBase<AsyncValue<State>>
-    with
-        OverrideWithValueMixin<AsyncValue<State>>,
-        OverrideWithProviderMixin<AsyncValue<State>,
-            AlwaysAliveProviderBase<AsyncValue<State>>> {
+/// {@template riverpod.streamprovider}
+/// Creates a stream and exposes its latest event.
+///
+/// [StreamProvider] is identical in behavior/usage to [FutureProvider], modulo
+/// the fact that the value created is a [Stream] instead of a [Future].
+///
+/// It can be used to express a value asynchronously loaded that can change over
+/// time, such as an editable `Message` coming from a web socket:
+///
+/// ```dart
+/// final messageProvider = StreamProvider.autoDispose<String>((ref) async* {
+///   // Open the connection
+///   final channel = IOWebSocketChannel.connect('ws://echo.websocket.org');
+///
+///   // Close the connection when the stream is destroyed
+///   ref.onDispose(() => channel.sink.close());
+///
+///   // Parse the value received and emit a Message instance
+///   await for (final value in channel.stream) {
+///     yield value.toString();
+///   }
+/// });
+/// ```
+///
+/// Which the UI can then listen:
+///
+/// ```dart
+/// Widget build(BuildContext context, WidgetRef ref) {
+///   AsyncValue<String> message = ref.watch(messageProvider);
+///
+///   return message.when(
+///     loading: () => const CircularProgressIndicator(),
+///     error: (err, stack) => Text('Error: $err'),
+///     data: (message) {
+///       return Text(message);
+///     },
+///   );
+/// }
+/// ```
+///
+/// **Note**:
+/// When listening to web sockets, firebase, or anything that consumes resources,
+/// it is important to use [StreamProvider.autoDispose] instead of simply [StreamProvider].
+///
+/// This ensures that the resources are released when no longer needed as,
+/// by default, a [StreamProvider] is almost never destroyed.
+///
+/// See also:
+///
+/// - [Provider], a provider that synchronously creates a value
+/// - [FutureProvider], a provider that asynchronously exposes a value that
+///   can change over time.
+/// - [stream], to obtain the [Stream] created instead of an [AsyncValue].
+/// - [future], to obtain the last value emitted by a [Stream].
+/// - [StreamProvider.family], to create a [StreamProvider] from external parameters
+/// - [StreamProvider.autoDispose], to destroy the state of a [StreamProvider] when no longer needed.
+/// {@endtemplate}
+class StreamProvider<T> extends _StreamProviderBase<T>
+    with AlwaysAliveProviderBase<AsyncValue<T>>, AlwaysAliveAsyncSelector<T> {
   /// {@macro riverpod.streamprovider}
   StreamProvider(
-    this._create, {
-    String? name,
-    this.dependencies,
-    Family? from,
-    Object? argument,
-  }) : super(name: name, from: from, argument: argument);
-
-  /// {@macro riverpod.family}
-  static const family = StreamProviderFamilyBuilder();
+    this._createFn, {
+    super.name,
+    super.from,
+    super.argument,
+    super.dependencies,
+  }) : super(cacheTime: null, disposeDelay: null);
 
   /// {@macro riverpod.autoDispose}
   static const autoDispose = AutoDisposeStreamProviderBuilder();
 
-  @override
-  ProviderBase<AsyncValue<State>> get originProvider => this;
+  /// {@macro riverpod.family}
+  static const family = StreamProviderFamilyBuilder();
 
-  final Create<Stream<State>, StreamProviderRef<State>> _create;
+  final Stream<T> Function(StreamProviderRef<T> ref) _createFn;
 
   @override
-  final List<ProviderOrFamily>? dependencies;
-
-  /// {@template riverpod.streamprovider.stream}
-  /// Exposes the [Stream] created by a [StreamProvider].
-  ///
-  /// The stream obtained is not strictly identical to the stream created.
-  /// Instead, this stream is always a broadcast stream.
-  ///
-  /// The stream obtained may change over time, if the [StreamProvider] is
-  /// re-evaluated, such as when it is using [Ref.watch] and the
-  /// provider being listened to changes, or on [ProviderContainer.refresh].
-  ///
-  /// If the [StreamProvider] was overridden using `overrideWithValue`,
-  /// a stream will be generated and manipulated based on the [AsyncValue] used.
-  /// {@endtemplate}
-  late final AlwaysAliveProviderBase<Stream<State>> stream =
-      AsyncValueAsStreamProvider(this, from: from, argument: argument);
-
-  /// {@template riverpod.streamprovider.future}
-  /// Exposes a [Future] that resolves with the last value or error emitted.
-  ///
-  /// This can be useful for scenarios where we want to read the current value
-  /// exposed by a [StreamProvider], but also handle the scenario were no
-  /// value were emitted yet:
-  ///
-  /// ```dart
-  /// final configsProvider = StreamProvider<Configuration>((ref) async* {
-  ///   // somehow emit a Configuration instance
-  /// });
-  ///
-  /// final productsProvider = FutureProvider<Products>((ref) async {
-  ///   // If a "Configuration" was emitted, retrieve it.
-  ///   // Otherwise, wait for a Configuration to be emitted.
-  ///   final configs = await ref.watch(configsProvider.future);
-  ///
-  ///   final response = await httpClient.get('${configs.host}/products');
-  ///   return Products.fromJson(response.data);
-  /// });
-  /// ```
-  ///
-  /// ## Why not use [StreamProvider.stream.first] instead?
-  ///
-  /// If you are familiar with streams, you may wonder why not use [Stream.first]
-  /// instead:
-  ///
-  /// ```dart
-  /// final configsProvider = StreamProvider<Configuration>((ref) {...});
-  ///
-  /// final productsProvider = FutureProvider<Products>((ref) async {
-  ///   final configs = await ref.watch(configsProvider.stream).first;
-  ///   ...
-  /// }
-  /// ```
-  ///
-  /// The problem with this code is, unless your [StreamProvider] is creating
-  /// a `BehaviorSubject` from `package:rxdart`, you have a bug.
-  ///
-  /// By default, if we call [Stream.first] **after** the first value was emitted,
-  /// then the [Future] created will not obtain that first value but instead
-  /// wait for a second one – which may never come.
-  ///
-  /// The following code demonstrate this problem:
-  ///
-  /// ```dart
-  /// final exampleProvider = StreamProvider<int>((ref) async* {
-  ///   yield 42;
-  /// });
-  ///
-  /// final anotherProvider = FutureProvider<void>((ref) async {
-  ///   print(await ref.watch(exampleProvider.stream).first);
-  ///   // The code will block here and wait forever
-  ///   print(await ref.watch(exampleProvider.stream).first);
-  ///   print('this code is never reached');
-  /// });
-  ///
-  /// void main() async {
-  ///   final container = ProviderContainer();
-  ///   await container.read(anotherProvider.future);
-  ///   // never reached
-  ///   print('done');
-  /// }
-  /// ```
-  ///
-  /// This snippet will print `42` once, then wait forever.
-  ///
-  /// On the other hand, if we used [StreamProvider.future], our code would
-  /// correctly execute:
-  ///
-  /// ```dart
-  /// final exampleProvider = StreamProvider<int>((ref) async* {
-  ///   yield 42;
-  /// });
-  ///
-  /// final anotherProvider = FutureProvider<void>((ref) async {
-  ///   print(await ref.watch(exampleProvider.future));
-  ///   print(await ref.watch(exampleProvider.future));
-  ///   print('completed');
-  /// });
-  ///
-  /// void main() async {
-  ///   final container = ProviderContainer();
-  ///   await container.read(anotherProvider.future);
-  ///   print('done');
-  /// }
-  /// ```
-  ///
-  /// with this modification, our code will now print:
-  ///
-  /// ```
-  /// 42
-  /// 42
-  /// completed
-  /// done
-  /// ```
-  ///
-  /// which is the expected behavior.
-  /// {@endtemplate}
-  late final AlwaysAliveProviderBase<Future<State>> future =
-      AsyncValueAsFutureProvider(this, from: from, argument: argument);
+  late final AlwaysAliveRefreshable<Future<T>> future = _future(this);
 
-  /// {@template riverpod.streamprovider.future}
-  @Deprecated('use `future` instead')
-  AlwaysAliveProviderBase<Future<State>> get last => future;
+  @override
+  late final AlwaysAliveRefreshable<Stream<T>> stream = _stream(this);
 
   @override
-  AsyncValue<State> create(covariant StreamProviderElement<State> ref) {
-    return ref._listenStream(() => _create(ref));
-  }
+  Stream<T> _create(StreamProviderElement<T> ref) => _createFn(ref);
 
   @override
-  bool updateShouldNotify(
-    AsyncValue<State> previousState,
-    AsyncValue<State> newState,
-  ) {
-    final wasLoading = previousState is AsyncLoading;
-    final isLoading = newState is AsyncLoading;
+  StreamProviderElement<T> createElement() => StreamProviderElement._(this);
+}
 
-    if (wasLoading || isLoading) return wasLoading != isLoading;
+/// The element of [StreamProvider].
+class StreamProviderElement<T> extends ProviderElementBase<AsyncValue<T>>
+    implements StreamProviderRef<T> {
+  StreamProviderElement._(_StreamProviderBase<T> provider) : super(provider);
 
-    return true;
-  }
+  final _futureNotifier = ProxyElementValueNotifier<Future<T>>();
+  Completer<T>? _completer;
 
-  @override
-  StreamProviderElement<State> createElement() => StreamProviderElement(this);
-}
+  final _streamNotifier = ProxyElementValueNotifier<Stream<T>>();
+  final StreamController<T> _streamController = StreamController<T>.broadcast();
 
-/// The Element of a [StreamProvider]
-class StreamProviderElement<State>
-    extends ProviderElementBase<AsyncValue<State>>
-    with _StreamProviderElementMixin<State>
-    implements StreamProviderRef<State> {
-  /// The Element of a [StreamProvider]
-  StreamProviderElement(StreamProvider<State> provider) : super(provider);
+  StreamSubscription<T>? _streamSubscription;
 
   @override
-  AsyncValue<State> get state => requireState;
+  AsyncValue<T> get state => requireState;
 
   @override
-  set state(AsyncValue<State> newState) => setState(newState);
-}
+  set state(AsyncValue<T> state) => setState(state);
 
-/// {@template riverpod.streamprovider.family}
-/// A class that allows building a [StreamProvider] from an external parameter.
-/// {@endtemplate}
-@sealed
-class StreamProviderFamily<State, Arg>
-    extends Family<AsyncValue<State>, Arg, StreamProvider<State>> {
-  /// {@macro riverpod.streamprovider.family}
-  StreamProviderFamily(
-    this._create, {
-    String? name,
-    List<ProviderOrFamily>? dependencies,
-  }) : super(name: name, dependencies: dependencies);
+  @override
+  void create() {
+    _streamNotifier.result ??= Result.data(_streamController.stream);
 
-  final FamilyCreate<Stream<State>, StreamProviderRef<State>, Arg> _create;
+    final streamResult = Result.guard(() {
+      final provider = this.provider as _StreamProviderBase<T>;
+      return provider._create(this);
+    });
 
-  @override
-  StreamProvider<State> create(Arg argument) {
-    return StreamProvider<State>(
-      (ref) => _create(ref, argument),
-      name: name,
-      from: this,
-      argument: argument,
+    streamResult.when(
+      data: _listenStream,
+      error: (err, stack) {
+        _futureNotifier.result = Result.data(
+          Future<T>.error(err, stack)
+            // TODO test ignore
+            ..ignore(),
+        );
+        setState(AsyncError<T>(err, stackTrace: stack));
+      },
+    );
+  }
+
+  @pragma('vm:prefer-inline')
+  void _listenStream(Stream<T> stream) {
+    setState(AsyncLoading<T>());
+
+    // TODO test that if a provider refreshes with before the stream has emitted a value,
+    // then .future isn't notifying listeners
+    if (_completer == null) {
+      final completer = _completer = Completer<T>();
+      _futureNotifier.result = Result.data(completer.future);
+    }
+
+    _streamSubscription = stream.listen(
+      (event) {
+        final completer = _completer;
+        if (completer != null) {
+          completer.complete(event);
+          _completer = null;
+          // TODO test that ref.read(p.future) after an event is emitted
+          // obtains a SynchronousFuture.
+          // Yet listeners of .future added before the first event aren't notified
+          _futureNotifier.UNSAFE_setResultWithoutNotifyingListeners(
+            Result.data(SynchronousFuture(event)),
+          );
+        } else {
+          _futureNotifier.result = Result.data(SynchronousFuture(event));
+        }
+
+        setState(AsyncData(event));
+        _streamController.add(event);
+      },
+      // ignore: avoid_types_on_closure_parameters
+      onError: (Object err, StackTrace stack) {
+        final completer = _completer;
+        if (completer != null) {
+          completer
+            ..completeError(err, stack)
+            // The error is already sent to the Zone through the original Stream
+            // so no need for this Future to send the error to the Zone too.
+            ..future.ignore();
+          _completer = null;
+          // TODO can we have a SynchronousFutureError?
+        } else {
+          _futureNotifier.result = Result.data(
+            Future<T>.error(err, stack)
+              // TODO test ignore
+              ..ignore(),
+          );
+        }
+
+        setState(AsyncError<T>(err, stackTrace: stack));
+        _streamController.addError(err, stack);
+      },
     );
   }
 
   @override
-  void setupOverride(Arg argument, SetupOverride setup) {
-    final provider = call(argument);
-    setup(origin: provider, override: provider);
+  void runOnDispose() {
+    super.runOnDispose();
+    _streamSubscription?.cancel();
   }
 
-  /// {@macro riverpod.overridewithprovider}
-  Override overrideWithProvider(
-    AlwaysAliveProviderBase<AsyncValue<State>> Function(Arg argument) override,
-  ) {
-    return FamilyOverride<Arg>(this, (arg, setup) {
-      final provider = call(arg);
-      setup(origin: provider, override: override(arg));
-    });
+  @override
+  void dispose() {
+    super.dispose();
+
+    /// The controller isn't recreated on provider rebuild. So we only close it
+    /// when the element is destroyed, not on "ref.onDispose".
+    _streamController.close();
   }
+
+  @override
+  void visitChildren({
+    required void Function(ProviderElementBase element) elementVisitor,
+    required void Function(ProxyElementValueNotifier element) notifierVisitor,
+  }) {
+    super.visitChildren(
+      elementVisitor: elementVisitor,
+      notifierVisitor: notifierVisitor,
+    );
+    notifierVisitor(_futureNotifier);
+    notifierVisitor(_streamNotifier);
+  }
+}
+
+/// The [Family] of [StreamProvider].
+class StreamProviderFamily<R, Arg> extends FamilyBase<StreamProviderRef<R>,
+    AsyncValue<R>, Arg, Stream<R>, StreamProvider<R>> {
+  /// The [Family] of [StreamProvider].
+  StreamProviderFamily(
+    super.create, {
+    super.name,
+    super.dependencies,
+  }) : super(providerFactory: StreamProvider<R>.new);
 }
diff --git a/packages/riverpod/lib/src/synchronous_future.dart b/packages/riverpod/lib/src/synchronous_future.dart
new file mode 100644
index 0000000000..3dae51fb4a
--- /dev/null
+++ b/packages/riverpod/lib/src/synchronous_future.dart
@@ -0,0 +1,69 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+/// A [Future] whose [then] implementation calls the callback immediately.
+///
+/// This is similar to [Future.value], except that the value is available in
+/// the same event-loop iteration.
+///
+/// ⚠ This class is useful in cases where you want to expose a single API, where
+/// you normally want to have everything execute synchronously, but where on
+/// rare occasions you want the ability to switch to an asynchronous model. **In
+/// general use of this class should be avoided as it is very difficult to debug
+/// such bimodal behavior.**
+class SynchronousFuture<T> implements Future<T> {
+  /// Creates a synchronous future.
+  ///
+  /// See also:
+  ///
+  ///  * [Future.value] for information about creating a regular
+  ///    [Future] that completes with a value.
+  SynchronousFuture(this._value);
+
+  final T _value;
+
+  @override
+  Stream<T> asStream() {
+    final controller = StreamController<T>();
+    controller.add(_value);
+    controller.close();
+    return controller.stream;
+  }
+
+  @override
+  Future<T> catchError(Function onError, {bool Function(Object error)? test}) =>
+      Completer<T>().future;
+
+  @override
+  Future<R> then<R>(
+    FutureOr<R> Function(T value) onValue, {
+    Function? onError,
+  }) {
+    final dynamic result = onValue(_value);
+    if (result is Future<R>) {
+      return result;
+    }
+    return SynchronousFuture<R>(result as R);
+  }
+
+  @override
+  Future<T> timeout(Duration timeLimit, {FutureOr<T> Function()? onTimeout}) {
+    return Future<T>.value(_value).timeout(timeLimit, onTimeout: onTimeout);
+  }
+
+  @override
+  Future<T> whenComplete(FutureOr<dynamic> Function() action) {
+    try {
+      final result = action();
+      if (result is Future) {
+        return result.then<T>((dynamic value) => _value);
+      }
+      return this;
+    } catch (e, stack) {
+      return Future<T>.error(e, stack);
+    }
+  }
+}
diff --git a/packages/riverpod/lib/src/value_provider.dart b/packages/riverpod/lib/src/value_provider.dart
index d7b76d31fa..3659332f0c 100644
--- a/packages/riverpod/lib/src/value_provider.dart
+++ b/packages/riverpod/lib/src/value_provider.dart
@@ -1,23 +1,29 @@
 import 'package:meta/meta.dart';
 
 import 'framework.dart';
+import 'result.dart';
 
 /// A provider that is driven by a value instead of a function.
 ///
 /// This is an implementation detail of `overrideWithValue`.
 @sealed
-class ValueProvider<State> extends AlwaysAliveProviderBase<State> {
+class ValueProvider<State> extends ProviderBase<State>
+    with AlwaysAliveProviderBase<State> {
   /// Creates a [ValueProvider].
-  ValueProvider(this._value) : super(name: null, from: null, argument: null);
+  ValueProvider(this._value)
+      : super(
+          name: null,
+          from: null,
+          argument: null,
+          cacheTime: null,
+          disposeDelay: null,
+        );
 
   final State _value;
 
   @override
   List<ProviderOrFamily>? get dependencies => null;
 
-  @override
-  State create(ValueProviderElement<State> ref) => _value;
-
   @override
   bool updateShouldNotify(State previousState, State newState) {
     return true;
@@ -54,4 +60,10 @@ class ValueProviderElement<State> extends ProviderElementBase<State> {
       onChange?.call(newValue);
     }
   }
+
+  @override
+  void create() {
+    final provider = this.provider as ValueProvider<State>;
+    setState(provider._value);
+  }
 }
diff --git a/packages/riverpod_cli/fixtures/unified_syntax/golden/widgets.dart b/packages/riverpod_cli/fixtures/unified_syntax/golden/widgets.dart
index cfc1455c1b..1656d5000c 100644
--- a/packages/riverpod_cli/fixtures/unified_syntax/golden/widgets.dart
+++ b/packages/riverpod_cli/fixtures/unified_syntax/golden/widgets.dart
@@ -7,6 +7,11 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 // ignore: unnecessary_import
 import 'package:riverpod/riverpod.dart';
 
+extension on ProviderBase {
+  // ignore: unused_element
+  Override overrideWithValue(Object? value) => throw UnimplementedError();
+}
+
 class Counter extends StateNotifier<int> {
   Counter(Ref this.ref) : super(1);
   final Ref ref;
diff --git a/packages/riverpod_cli/fixtures/unified_syntax/input/widgets.dart b/packages/riverpod_cli/fixtures/unified_syntax/input/widgets.dart
index c39c9d4497..e720a84c2b 100644
--- a/packages/riverpod_cli/fixtures/unified_syntax/input/widgets.dart
+++ b/packages/riverpod_cli/fixtures/unified_syntax/input/widgets.dart
@@ -7,6 +7,11 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 // ignore: unnecessary_import
 import 'package:riverpod/riverpod.dart';
 
+extension on ProviderBase {
+  // ignore: unused_element
+  Override overrideWithValue(Object? value) => throw UnimplementedError();
+}
+
 class Counter extends StateNotifier<int> {
   Counter(ProviderReference this.ref) : super(1);
   final ProviderReference ref;


Test patch:
diff --git a/packages/flutter_riverpod/test/auto_dispose_change_notifier_provider_test.dart b/packages/flutter_riverpod/test/auto_dispose_change_notifier_provider_test.dart
index 2c6741af81..aa1cd61ab3 100644
--- a/packages/flutter_riverpod/test/auto_dispose_change_notifier_provider_test.dart
+++ b/packages/flutter_riverpod/test/auto_dispose_change_notifier_provider_test.dart
@@ -136,54 +136,54 @@ void main() {
     expect(notifier.mounted, isFalse);
   });
 
-  test(
-      'overrideWithValue listens to the notifier, support notifier change, and does not dispose of the notifier',
-      () async {
-    final provider = ChangeNotifierProvider.autoDispose((_) => TestNotifier());
-    final notifier = TestNotifier();
-    final notifier2 = TestNotifier();
-    final container = ProviderContainer(overrides: [
-      provider.overrideWithValue(notifier),
-    ]);
-    addTearDown(container.dispose);
-
-    var callCount = 0;
-    final sub = container.listen(provider, (_, __) => callCount++);
-    final notifierSub = container.listen(provider.notifier, (_, __) {});
-
-    expect(sub.read(), notifier);
-    expect(callCount, 0);
-    expect(notifierSub.read(), notifier);
-    expect(notifier.hasListeners, true);
-
-    notifier.count++;
-
-    await container.pump();
-    expect(callCount, 1);
-
-    container.updateOverrides([
-      provider.overrideWithValue(notifier2),
-    ]);
-
-    await container.pump();
-    expect(callCount, 2);
-    expect(notifier.hasListeners, false);
-    expect(notifier2.hasListeners, true);
-    expect(notifier.mounted, true);
-    expect(notifierSub.read(), notifier2);
-
-    notifier2.count++;
-
-    await container.pump();
-    expect(callCount, 3);
-
-    container.dispose();
-
-    expect(callCount, 3);
-    expect(notifier2.hasListeners, false);
-    expect(notifier2.mounted, true);
-    expect(notifier.mounted, true);
-  });
+  // test(
+  //     'overrideWithValue listens to the notifier, support notifier change, and does not dispose of the notifier',
+  //     () async {
+  //   final provider = ChangeNotifierProvider.autoDispose((_) => TestNotifier());
+  //   final notifier = TestNotifier();
+  //   final notifier2 = TestNotifier();
+  //   final container = ProviderContainer(overrides: [
+  //     provider.overrideWithValue(notifier),
+  //   ]);
+  //   addTearDown(container.dispose);
+
+  //   var callCount = 0;
+  //   final sub = container.listen(provider, (_, __) => callCount++);
+  //   final notifierSub = container.listen(provider.notifier, (_, __) {});
+
+  //   expect(sub.read(), notifier);
+  //   expect(callCount, 0);
+  //   expect(notifierSub.read(), notifier);
+  //   expect(notifier.hasListeners, true);
+
+  //   notifier.count++;
+
+  //   await container.pump();
+  //   expect(callCount, 1);
+
+  //   container.updateOverrides([
+  //     provider.overrideWithValue(notifier2),
+  //   ]);
+
+  //   await container.pump();
+  //   expect(callCount, 2);
+  //   expect(notifier.hasListeners, false);
+  //   expect(notifier2.hasListeners, true);
+  //   expect(notifier.mounted, true);
+  //   expect(notifierSub.read(), notifier2);
+
+  //   notifier2.count++;
+
+  //   await container.pump();
+  //   expect(callCount, 3);
+
+  //   container.dispose();
+
+  //   expect(callCount, 3);
+  //   expect(notifier2.hasListeners, false);
+  //   expect(notifier2.mounted, true);
+  //   expect(notifier.mounted, true);
+  // });
 }
 
 class OnDisposeMock extends Mock {
diff --git a/packages/flutter_riverpod/test/consumer_test.dart b/packages/flutter_riverpod/test/consumer_test.dart
index a5cf688252..316780af7f 100644
--- a/packages/flutter_riverpod/test/consumer_test.dart
+++ b/packages/flutter_riverpod/test/consumer_test.dart
@@ -364,91 +364,91 @@ void main() {
     expect(buildCount, 2);
   });
 
-  testWidgets('remove listener when changing container', (tester) async {
-    final notifier = TestNotifier();
-    final provider = StateNotifierProvider<TestNotifier, int>((_) {
-      return notifier;
-    }, name: 'provider');
-    final notifier2 = TestNotifier(42);
-    const firstOwnerKey = Key('first');
-    const secondOwnerKey = Key('second');
-    final key = GlobalKey();
-
-    final consumer = Consumer(
-        builder: (context, ref, _) {
-          final value = ref.watch(provider);
-          return Text('$value', textDirection: TextDirection.ltr);
-        },
-        key: key);
-
-    await tester.pumpWidget(
-      Column(
-        children: [
-          ProviderScope(
-            key: firstOwnerKey,
-            child: consumer,
-          ),
-          ProviderScope(
-            key: secondOwnerKey,
-            overrides: [
-              provider.overrideWithValue(notifier2),
-            ],
-            child: Container(),
-          ),
-        ],
-      ),
-    );
-
-    final owner1 = tester //
-        .firstState<ProviderScopeState>(find.byKey(firstOwnerKey))
-        .container;
-
-    final state1 = owner1
-        .getAllProviderElements()
-        .firstWhere((s) => s.provider == provider);
-
-    expect(state1.hasListeners, true);
-    expect(find.text('0'), findsOneWidget);
-
-    await tester.pumpWidget(
-      Column(
-        children: [
-          ProviderScope(
-            key: firstOwnerKey,
-            child: Container(),
-          ),
-          ProviderScope(
-            key: secondOwnerKey,
-            overrides: [
-              provider.overrideWithValue(notifier2),
-            ],
-            child: consumer,
-          ),
-        ],
-      ),
-    );
-
-    final container2 = tester //
-        .firstState<ProviderScopeState>(find.byKey(secondOwnerKey))
-        .container;
-
-    final state2 = container2
-        .getAllProviderElements()
-        .firstWhere((s) => s.provider is StateNotifierProvider);
-
-    expect(find.text('0'), findsNothing);
-    expect(find.text('42'), findsOneWidget);
-    expect(state1.hasListeners, false);
-    expect(state2.hasListeners, true);
-
-    notifier2.increment();
-    await tester.pump();
-
-    expect(find.text('0'), findsNothing);
-    expect(find.text('43'), findsOneWidget);
-    expect(state1.hasListeners, false);
-    expect(state2.hasListeners, true);
-  });
+  // testWidgets('remove listener when changing container', (tester) async {
+  //   final notifier = TestNotifier();
+  //   final provider = StateNotifierProvider<TestNotifier, int>((_) {
+  //     return notifier;
+  //   }, name: 'provider');
+  //   final notifier2 = TestNotifier(42);
+  //   const firstOwnerKey = Key('first');
+  //   const secondOwnerKey = Key('second');
+  //   final key = GlobalKey();
+
+  //   final consumer = Consumer(
+  //       builder: (context, ref, _) {
+  //         final value = ref.watch(provider);
+  //         return Text('$value', textDirection: TextDirection.ltr);
+  //       },
+  //       key: key);
+
+  //   await tester.pumpWidget(
+  //     Column(
+  //       children: [
+  //         ProviderScope(
+  //           key: firstOwnerKey,
+  //           child: consumer,
+  //         ),
+  //         ProviderScope(
+  //           key: secondOwnerKey,
+  //           overrides: [
+  //             provider.overrideWithValue(notifier2),
+  //           ],
+  //           child: Container(),
+  //         ),
+  //       ],
+  //     ),
+  //   );
+
+  //   final owner1 = tester //
+  //       .firstState<ProviderScopeState>(find.byKey(firstOwnerKey))
+  //       .container;
+
+  //   final state1 = owner1
+  //       .getAllProviderElements()
+  //       .firstWhere((s) => s.provider == provider);
+
+  //   expect(state1.hasListeners, true);
+  //   expect(find.text('0'), findsOneWidget);
+
+  //   await tester.pumpWidget(
+  //     Column(
+  //       children: [
+  //         ProviderScope(
+  //           key: firstOwnerKey,
+  //           child: Container(),
+  //         ),
+  //         ProviderScope(
+  //           key: secondOwnerKey,
+  //           overrides: [
+  //             provider.overrideWithValue(notifier2),
+  //           ],
+  //           child: consumer,
+  //         ),
+  //       ],
+  //     ),
+  //   );
+
+  //   final container2 = tester //
+  //       .firstState<ProviderScopeState>(find.byKey(secondOwnerKey))
+  //       .container;
+
+  //   final state2 = container2
+  //       .getAllProviderElements()
+  //       .firstWhere((s) => s.provider is StateNotifierProvider);
+
+  //   expect(find.text('0'), findsNothing);
+  //   expect(find.text('42'), findsOneWidget);
+  //   expect(state1.hasListeners, false);
+  //   expect(state2.hasListeners, true);
+
+  //   notifier2.increment();
+  //   await tester.pump();
+
+  //   expect(find.text('0'), findsNothing);
+  //   expect(find.text('43'), findsOneWidget);
+  //   expect(state1.hasListeners, false);
+  //   expect(state2.hasListeners, true);
+  // });
 
   testWidgets('remove listener when destroying the consumer', (tester) async {
     final notifier = TestNotifier();
diff --git a/packages/flutter_riverpod/test/framework_test.dart b/packages/flutter_riverpod/test/framework_test.dart
index 6e03364fc0..7b3f1010c9 100644
--- a/packages/flutter_riverpod/test/framework_test.dart
+++ b/packages/flutter_riverpod/test/framework_test.dart
@@ -344,28 +344,28 @@ void main() {
     expect(ref.refresh(provider), null);
   });
 
-  testWidgets('ProviderScope allows specifying a ProviderContainer',
-      (tester) async {
-    final provider = FutureProvider((ref) async => 42);
-    late WidgetRef ref;
-    final container = createContainer(overrides: [
-      provider.overrideWithValue(const AsyncValue.data(42)),
-    ]);
-
-    await tester.pumpWidget(
-      UncontrolledProviderScope(
-        container: container,
-        child: Consumer(
-          builder: (context, r, _) {
-            ref = r;
-            return Container();
-          },
-        ),
-      ),
-    );
-
-    expect(ref.read(provider), const AsyncValue.data(42));
-  });
+  // testWidgets('ProviderScope allows specifying a ProviderContainer',
+  //     (tester) async {
+  //   final provider = FutureProvider((ref) async => 42);
+  //   late WidgetRef ref;
+  //   final container = createContainer(overrides: [
+  //     provider.overrideWithValue(const AsyncValue.data(42)),
+  //   ]);
+
+  //   await tester.pumpWidget(
+  //     UncontrolledProviderScope(
+  //       container: container,
+  //       child: Consumer(
+  //         builder: (context, r, _) {
+  //           ref = r;
+  //           return Container();
+  //         },
+  //       ),
+  //     ),
+  //   );
+
+  //   expect(ref.read(provider), const AsyncValue.data(42));
+  // });
 
   testWidgets('AlwaysAliveProviderBase.read(context) inside initState',
       (tester) async {
@@ -655,36 +655,6 @@ void main() {
     });
   });
 
-  testWidgets(
-      'autoDispose initState and ProviderListener does not destroy the state',
-      (tester) async {
-    var disposeCount = 0;
-    final counterProvider = StateProvider.autoDispose((ref) {
-      ref.onDispose(() => disposeCount++);
-      return 0;
-    });
-
-    await tester.pumpWidget(
-      ProviderScope(
-        child: Demo(
-          initState: (context, ref) {
-            ref.read(counterProvider.state).addListener((state) {});
-          },
-          builder: (context, ref) {
-            // ignore: deprecated_member_use_from_same_package
-            return ProviderListener(
-              onChange: (ct, prev, value) {},
-              provider: counterProvider,
-              child: Container(),
-            );
-          },
-        ),
-      ),
-    );
-
-    expect(disposeCount, 0);
-  });
-
   testWidgets('autoDispose states are kept alive during pushReplacement',
       (tester) async {
     var disposeCount = 0;
diff --git a/packages/flutter_riverpod/test/future_provider_test.dart b/packages/flutter_riverpod/test/future_provider_test.dart
index 8c08557340..9270211feb 100644
--- a/packages/flutter_riverpod/test/future_provider_test.dart
+++ b/packages/flutter_riverpod/test/future_provider_test.dart
@@ -122,215 +122,215 @@ void main() {
   });
 
   group('overrideWithValue', () {
-    var callCount = 0;
-    final futureProvider = FutureProvider((s) async {
-      callCount++;
-      return 42;
-    });
-
-    Future<int>? future;
-    var completed = false;
-    final proxy = Provider<String>(
-      (ref) {
-        final first = ref.watch(futureProvider.future);
-        future = first
-          ..then(
-            (value) => completed = true,
-            onError: (dynamic _) => completed = true,
-          );
-        return '';
-      },
-    );
-
-    setUp(() {
-      callCount = 0;
-      completed = false;
-      future = null;
-    });
-
-    final child = Directionality(
-      textDirection: TextDirection.ltr,
-      child: Consumer(builder: (c, ref, _) {
-        ref.watch(proxy);
-        return ref.watch(futureProvider).when(
-              data: (data) => Text(data.toString()),
-              loading: () => const Text('loading'),
-              error: (err, stack) {
-                return const Text('error');
-              },
-            );
-      }),
-    );
-
-    testWidgets('no-op if completed and rebuild with same value',
-        (tester) async {
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.data(42)),
-          ],
-          child: child,
-        ),
-      );
-
-      expect(completed, true);
-      await expectLater(future, completion(42));
-
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.data(42)),
-          ],
-          child: child,
-        ),
-      );
-    });
-
-    testWidgets(
-        'FutureProviderDependency.future completes on rebuild with data',
-        (tester) async {
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.loading()),
-          ],
-          child: child,
-        ),
-      );
-
-      // make sure the future doesn't just complete in one frame
-      await Future<void>.value();
-
-      expect(completed, false);
-      expect(future, isNotNull);
-
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.data(42)),
-          ],
-          child: child,
-        ),
-      );
-
-      expect(completed, true);
-      await expectLater(future, completion(42));
-    });
-
-    testWidgets(
-        'FutureProviderDependency.future completes on rebuild with error',
-        (tester) async {
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.loading()),
-          ],
-          child: child,
-        ),
-      );
-
-      // make sure the future doesn't just complete in one frame
-      await Future<void>.value();
-
-      expect(completed, false);
-      expect(future, isNotNull);
-
-      final error = Error();
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(AsyncValue.error(error)),
-          ],
-          child: child,
-        ),
-      );
-
-      expect(completed, true);
-      await expectLater(future, throwsA(error));
-    });
-
-    testWidgets('FutureProviderDependency.future loading to loading is no-op',
-        (tester) async {
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.loading()),
-          ],
-          child: child,
-        ),
-      );
-
-      expect(completed, false);
-      expect(future, isNotNull);
-
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.loading()),
-          ],
-          child: child,
-        ),
-      );
-
-      // make sure the future doesn't just complete in one frame
-      await Future<void>.value();
-
-      expect(completed, false);
-      expect(future, isNotNull);
-    });
-
-    testWidgets('Initial build as loading', (tester) async {
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.loading()),
-          ],
-          child: child,
-        ),
-      );
-
-      expect(callCount, 0);
-      expect(find.text('loading'), findsOneWidget);
-
-      expect(completed, false);
-      expect(future, isNotNull);
-    });
-
-    testWidgets('Initial build as value', (tester) async {
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(const AsyncValue.data(42)),
-          ],
-          child: child,
-        ),
-      );
-
-      expect(callCount, 0);
-      expect(find.text('42'), findsOneWidget);
-
-      expect(completed, true);
-      await expectLater(future, completion(42));
-    });
-
-    testWidgets('Initial build as error', (tester) async {
-      final error = Error();
-
-      await tester.pumpWidget(
-        ProviderScope(
-          overrides: [
-            futureProvider.overrideWithValue(AsyncValue.error(error)),
-          ],
-          child: child,
-        ),
-      );
-
-      expect(callCount, 0);
-      expect(find.text('error'), findsOneWidget);
-
-      expect(completed, true);
-      await expectLater(future, throwsA(error));
-    });
+    // var callCount = 0;
+    // final futureProvider = FutureProvider((s) async {
+    //   callCount++;
+    //   return 42;
+    // });
+
+    // Future<int>? future;
+    // var completed = false;
+    // final proxy = Provider<String>(
+    //   (ref) {
+    //     final first = ref.watch(futureProvider.future);
+    //     future = first
+    //       ..then(
+    //         (value) => completed = true,
+    //         onError: (dynamic _) => completed = true,
+    //       );
+    //     return '';
+    //   },
+    // );
+
+    // setUp(() {
+    //   callCount = 0;
+    //   completed = false;
+    //   future = null;
+    // });
+
+    // final child = Directionality(
+    //   textDirection: TextDirection.ltr,
+    //   child: Consumer(builder: (c, ref, _) {
+    //     ref.watch(proxy);
+    //     return ref.watch(futureProvider).when(
+    //           data: (data) => Text(data.toString()),
+    //           loading: () => const Text('loading'),
+    //           error: (err, stack) {
+    //             return const Text('error');
+    //           },
+    //         );
+    //   }),
+    // );
+
+    //   testWidgets('no-op if completed and rebuild with same value',
+    //       (tester) async {
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.data(42)),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     expect(completed, true);
+    //     await expectLater(future, completion(42));
+
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.data(42)),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+    //   });
+
+    //   testWidgets(
+    //       'FutureProviderDependency.future completes on rebuild with data',
+    //       (tester) async {
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.loading()),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     // make sure the future doesn't just complete in one frame
+    //     await Future<void>.value();
+
+    //     expect(completed, false);
+    //     expect(future, isNotNull);
+
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.data(42)),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     expect(completed, true);
+    //     await expectLater(future, completion(42));
+    //   });
+
+    //   testWidgets(
+    //       'FutureProviderDependency.future completes on rebuild with error',
+    //       (tester) async {
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.loading()),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     // make sure the future doesn't just complete in one frame
+    //     await Future<void>.value();
+
+    //     expect(completed, false);
+    //     expect(future, isNotNull);
+
+    //     final error = Error();
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(AsyncValue.error(error)),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     expect(completed, true);
+    //     await expectLater(future, throwsA(error));
+    //   });
+
+    //   testWidgets('FutureProviderDependency.future loading to loading is no-op',
+    //       (tester) async {
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.loading()),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     expect(completed, false);
+    //     expect(future, isNotNull);
+
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.loading()),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     // make sure the future doesn't just complete in one frame
+    //     await Future<void>.value();
+
+    //     expect(completed, false);
+    //     expect(future, isNotNull);
+    //   });
+
+    //   testWidgets('Initial build as loading', (tester) async {
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.loading()),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     expect(callCount, 0);
+    //     expect(find.text('loading'), findsOneWidget);
+
+    //     expect(completed, false);
+    //     expect(future, isNotNull);
+    //   });
+
+    //   testWidgets('Initial build as value', (tester) async {
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(const AsyncValue.data(42)),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     expect(callCount, 0);
+    //     expect(find.text('42'), findsOneWidget);
+
+    //     expect(completed, true);
+    //     await expectLater(future, completion(42));
+    //   });
+
+    //   testWidgets('Initial build as error', (tester) async {
+    //     final error = Error();
+
+    //     await tester.pumpWidget(
+    //       ProviderScope(
+    //         overrides: [
+    //           futureProvider.overrideWithValue(AsyncValue.error(error)),
+    //         ],
+    //         child: child,
+    //       ),
+    //     );
+
+    //     expect(callCount, 0);
+    //     expect(find.text('error'), findsOneWidget);
+
+    //     expect(completed, true);
+    //     await expectLater(future, throwsA(error));
+    //   });
   });
 
   testWidgets('FutureProvider into FutureProviderFamily', (tester) async {
diff --git a/packages/flutter_riverpod/test/provider_listener_test.dart b/packages/flutter_riverpod/test/provider_listener_test.dart
deleted file mode 100644
index f7e6ba58e5..0000000000
--- a/packages/flutter_riverpod/test/provider_listener_test.dart
+++ /dev/null
@@ -1,390 +0,0 @@
-// ignore_for_file: deprecated_member_use_from_same_package
-import 'package:flutter/material.dart' hide Listener;
-import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:flutter_test/flutter_test.dart';
-import 'package:mockito/mockito.dart';
-
-import 'utils.dart';
-
-void main() {
-  group('ProviderListener', () {
-    testWidgets('can downcast the value', (tester) async {
-      final dep = StateProvider((ref) => 0);
-      final provider = Provider((ref) => ref.watch(dep.state).state);
-
-      final container = createContainer();
-      final listener = Listener<num>();
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<num>(
-            provider: provider,
-            onChange: (c, prev, value) => listener(prev, value),
-            child: Container(),
-          ),
-        ),
-      );
-
-      verifyZeroInteractions(listener);
-
-      container.read(dep.state).state++;
-      await tester.pump();
-
-      verifyOnly(listener, listener(0, 1));
-    });
-
-    testWidgets('works with providers that returns null', (tester) async {
-      final nullProvider = Provider((ref) => null);
-
-      // should compile
-      ProviderListener<void>(
-        provider: nullProvider,
-        onChange: (context, prev, value) {},
-        child: Container(),
-      );
-    });
-
-    testWidgets('receives the buildContext as a parameter on change',
-        (tester) async {
-      final provider = StateProvider((ref) => 0);
-      final key = GlobalKey();
-      BuildContext? context;
-      final container = createContainer();
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<StateController<int>>(
-            key: key,
-            provider: provider.state,
-            onChange: (c, _, __) => context = c,
-            child: Container(),
-          ),
-        ),
-      );
-
-      container.read(provider.state).state++;
-
-      expect(context, key.currentContext);
-    });
-
-    testWidgets('renders child', (tester) async {
-      final provider = StateProvider((ref) => 0);
-
-      await tester.pumpWidget(
-        ProviderScope(
-          child: ProviderListener<StateController<int>>(
-            provider: provider.state,
-            onChange: (_, prev, value) {},
-            child: const Text('hello', textDirection: TextDirection.ltr),
-          ),
-        ),
-      );
-
-      expect(find.text('hello'), findsOneWidget);
-    });
-
-    testWidgets('calls onChange at the end of frame after a mayHaveChanged',
-        (tester) async {
-      final container = createContainer();
-      final provider = StateProvider((ref) => 0);
-      final onChange = Listener<int>();
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<StateController<int>>(
-            provider: provider.state,
-            onChange: (_, prev, value) => onChange(prev?.state, value.state),
-            child: Container(),
-          ),
-        ),
-      );
-
-      verifyZeroInteractions(onChange);
-
-      container.read(provider.state).state++;
-
-      verifyOnly(onChange, onChange(1, 1));
-    });
-
-    testWidgets('can mark parents as dirty during onChange', (tester) async {
-      final container = createContainer();
-      final provider = StateProvider((ref) => 0);
-      final onChange = Listener<int>();
-
-      await tester.pumpWidget(
-        StatefulBuilder(
-          builder: (context, setState) {
-            return UncontrolledProviderScope(
-              container: container,
-              child: ProviderListener<StateController<int>>(
-                provider: provider.state,
-                onChange: (_, prev, value) => setState(() {}),
-                child: Container(),
-              ),
-            );
-          },
-        ),
-      );
-
-      verifyZeroInteractions(onChange);
-
-      // This would fail if the setState was not allowed
-      container.read(provider.state).state++;
-    });
-
-    testWidgets('calls onChange synchronously if possible', (tester) async {
-      final provider = StateProvider((ref) => 0);
-      final onChange = Listener<int>();
-      final container = createContainer();
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<StateController<int>>(
-            provider: provider.state,
-            onChange: (_, prev, value) => onChange(prev?.state, value.state),
-            child: Container(),
-          ),
-        ),
-      );
-      verifyZeroInteractions(onChange);
-
-      container.read(provider.state).state++;
-      container.read(provider.state).state++;
-      container.read(provider.state).state++;
-
-      verifyInOrder([
-        onChange(1, 1),
-        onChange(2, 2),
-        onChange(3, 3),
-      ]);
-      verifyNoMoreInteractions(onChange);
-    });
-
-    testWidgets('calls onChange asynchronously if the change is indirect',
-        (tester) async {
-      final provider = StateProvider((ref) => 0);
-      final isEven = Provider((ref) => ref.watch(provider.state).state.isEven);
-      final onChange = Listener<bool>();
-      final container = createContainer();
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<bool>(
-            provider: isEven,
-            onChange: (_, prev, value) => onChange(prev, value),
-            child: Container(),
-          ),
-        ),
-      );
-      verifyZeroInteractions(onChange);
-
-      container.read(provider.state).state++;
-      container.read(provider.state).state++;
-      container.read(provider.state).state++;
-
-      verifyZeroInteractions(onChange);
-
-      await tester.pump();
-
-      verifyOnly(onChange, onChange(true, false));
-    });
-
-    group('supports null', () {
-      testWidgets('in didChangeDependencies', (tester) async {
-        await tester.pumpWidget(
-          ProviderScope(
-            child: ProviderListener<StateController<int>>(
-              provider: null,
-              onChange: (_, prev, value) {},
-              child: Container(),
-            ),
-          ),
-        );
-      });
-
-      testWidgets('in dispose', (tester) async {
-        await tester.pumpWidget(
-          ProviderScope(
-            child: ProviderListener<StateController<int>>(
-              provider: null,
-              onChange: (_, prev, value) {},
-              child: Container(),
-            ),
-          ),
-        );
-
-        await tester.pumpWidget(Container());
-      });
-    });
-
-    testWidgets('closes the subscription on dispose', (tester) async {
-      final provider = StateProvider((ref) => 0);
-      final onChange = Listener<int>();
-      final container = createContainer();
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<int>(
-            provider: provider,
-            onChange: (_, prev, value) => onChange(prev, value),
-            child: Container(),
-          ),
-        ),
-      );
-
-      expect(container.readProviderElement(provider).hasListeners, true);
-
-      await tester.pumpWidget(Container());
-
-      expect(container.readProviderElement(provider).hasListeners, false);
-    });
-
-    testWidgets('closes the subscription on provider change', (tester) async {
-      final provider = StateProvider.family<int, int>((ref, _) => 0);
-      final container = createContainer();
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<int>(
-            provider: provider(0),
-            onChange: (_, prev, value) {},
-            child: Container(),
-          ),
-        ),
-      );
-
-      expect(container.readProviderElement(provider(0)).hasListeners, true);
-      expect(container.readProviderElement(provider(1)).hasListeners, false);
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<int>(
-            provider: provider(1),
-            onChange: (_, prev, value) {},
-            child: Container(),
-          ),
-        ),
-      );
-
-      expect(container.readProviderElement(provider(0)).hasListeners, false);
-      expect(container.readProviderElement(provider(1)).hasListeners, true);
-    });
-
-    testWidgets('listen to the new provider on provider change',
-        (tester) async {
-      final provider = StateProvider.family<int, int>((ref, _) => 0);
-      final container = createContainer();
-      final onChange = Listener<int>();
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<StateController<int>>(
-            provider: provider(0).state,
-            onChange: (_, prev, value) => onChange(prev?.state, value.state),
-            child: Container(),
-          ),
-        ),
-      );
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<StateController<int>>(
-            provider: provider(1).state,
-            onChange: (_, prev, value) => onChange(prev?.state, value.state),
-            child: Container(),
-          ),
-        ),
-      );
-
-      verifyZeroInteractions(onChange);
-
-      container.read(provider(0).state).state++;
-      container.read(provider(1).state).state = 42;
-
-      await Future<void>.value();
-
-      verifyOnly(onChange, onChange(42, 42));
-    });
-
-    testWidgets('supports Changing the ProviderContainer', (tester) async {
-      final provider = Provider((ref) => 0);
-      final onChange = Listener<int>();
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(0),
-      ]);
-      final container2 = createContainer(overrides: [
-        provider.overrideWithValue(0),
-      ]);
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<int>(
-            provider: provider,
-            onChange: (_, prev, value) => onChange(prev, value),
-            child: Container(),
-          ),
-        ),
-      );
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container2,
-          child: ProviderListener<int>(
-            provider: provider,
-            onChange: (_, prev, value) => onChange(prev, value),
-            child: Container(),
-          ),
-        ),
-      );
-
-      container.updateOverrides([
-        provider.overrideWithValue(21),
-      ]);
-      container2.updateOverrides([
-        provider.overrideWithValue(42),
-      ]);
-
-      await Future<void>.value();
-
-      verifyOnly(onChange, onChange(0, 42));
-    });
-
-    testWidgets('supports scoping Providers', (tester) async {
-      final provider = Provider((ref) => 0);
-      final onChange = Listener<int>();
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(42),
-      ]);
-
-      await tester.pumpWidget(
-        UncontrolledProviderScope(
-          container: container,
-          child: ProviderListener<int>(
-            provider: provider,
-            onChange: (_, prev, value) => onChange(prev, value),
-            child: Container(),
-          ),
-        ),
-      );
-
-      container.updateOverrides([
-        provider.overrideWithValue(21),
-      ]);
-
-      await Future<void>.value();
-
-      verifyOnly(onChange, onChange(42, 21));
-    });
-  });
-}
diff --git a/packages/flutter_riverpod/test/providers/change_notifier/auto_dispose_change_notifier_provider_test.dart b/packages/flutter_riverpod/test/providers/change_notifier/auto_dispose_change_notifier_provider_test.dart
index fbd6ef4076..82516615f7 100644
--- a/packages/flutter_riverpod/test/providers/change_notifier/auto_dispose_change_notifier_provider_test.dart
+++ b/packages/flutter_riverpod/test/providers/change_notifier/auto_dispose_change_notifier_provider_test.dart
@@ -82,34 +82,32 @@ void main() {
           unorderedEquals(<Object>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.notifier)
           ]),
         );
         expect(root.getAllProviderElements(), isEmpty);
       });
 
-      test('when using provider.overrideWithValue', () {
-        final provider =
-            ChangeNotifierProvider.autoDispose((ref) => ValueNotifier(0));
-        final root = createContainer();
-        final container = createContainer(parent: root, overrides: [
-          provider.overrideWithValue(ValueNotifier(42)),
-        ]);
-
-        expect(container.read(provider.notifier).value, 42);
-        expect(container.read(provider).value, 42);
-        expect(
-          container.getAllProviderElements(),
-          unorderedEquals(<Object>[
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.notifier)
-          ]),
-        );
-        expect(root.getAllProviderElements(), isEmpty);
-      });
+      // test('when using provider.overrideWithValue', () {
+      //   final provider =
+      //       ChangeNotifierProvider.autoDispose((ref) => ValueNotifier(0));
+      //   final root = createContainer();
+      //   final container = createContainer(parent: root, overrides: [
+      //     provider.overrideWithValue(ValueNotifier(42)),
+      //   ]);
+
+      //   expect(container.read(provider.notifier).value, 42);
+      //   expect(container.read(provider).value, 42);
+      //   expect(
+      //     container.getAllProviderElements(),
+      //     unorderedEquals(<Object>[
+      //       isA<ProviderElementBase>()
+      //           .having((e) => e.origin, 'origin', provider),
+      //       isA<ProviderElementBase>()
+      //           .having((e) => e.origin, 'origin', provider.notifier)
+      //     ]),
+      //   );
+      //   expect(root.getAllProviderElements(), isEmpty);
+      // });
 
       test('when using provider.overrideWithProvider', () {
         final provider =
@@ -128,8 +126,6 @@ void main() {
           unorderedEquals(<Object>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.notifier)
           ]),
         );
         expect(root.getAllProviderElements(), isEmpty);
diff --git a/packages/flutter_riverpod/test/providers/change_notifier/change_notifier_provider_test.dart b/packages/flutter_riverpod/test/providers/change_notifier/change_notifier_provider_test.dart
index 30cc0c854f..05d7758da6 100644
--- a/packages/flutter_riverpod/test/providers/change_notifier/change_notifier_provider_test.dart
+++ b/packages/flutter_riverpod/test/providers/change_notifier/change_notifier_provider_test.dart
@@ -6,6 +6,23 @@ import 'package:mockito/mockito.dart';
 import '../../utils.dart';
 
 void main() {
+  test('ref.listenSelf listens to state changes', () {
+    final listener = Listener<ValueNotifier<int>>();
+    final container = createContainer();
+    final provider = ChangeNotifierProvider<ValueNotifier<int>>((ref) {
+      ref.listenSelf(listener);
+      return ValueNotifier(0);
+    });
+
+    final notifier = container.read(provider);
+
+    verifyOnly(listener, listener(null, notifier));
+
+    container.read(provider.notifier).value++;
+
+    verifyOnly(listener, listener(notifier, notifier));
+  });
+
   test('support null ChangeNotifier', () {
     final container = createContainer();
     final provider = ChangeNotifierProvider<ValueNotifier<int>?>((ref) => null);
@@ -90,33 +107,31 @@ void main() {
         unorderedEquals(<Object>[
           isA<ProviderElementBase>()
               .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier)
         ]),
       );
       expect(root.getAllProviderElements(), isEmpty);
     });
 
-    test('when using provider.overrideWithValue', () {
-      final provider = ChangeNotifierProvider((ref) => ValueNotifier(0));
-      final root = createContainer();
-      final container = createContainer(parent: root, overrides: [
-        provider.overrideWithValue(ValueNotifier(42)),
-      ]);
-
-      expect(container.read(provider.notifier).value, 42);
-      expect(container.read(provider).value, 42);
-      expect(
-        container.getAllProviderElements(),
-        unorderedEquals(<Object>[
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier)
-        ]),
-      );
-      expect(root.getAllProviderElements(), isEmpty);
-    });
+    // test('when using provider.overrideWithValue', () {
+    //   final provider = ChangeNotifierProvider((ref) => ValueNotifier(0));
+    //   final root = createContainer();
+    //   final container = createContainer(parent: root, overrides: [
+    //     provider.overrideWithValue(ValueNotifier(42)),
+    //   ]);
+
+    //   expect(container.read(provider.notifier).value, 42);
+    //   expect(container.read(provider).value, 42);
+    //   expect(
+    //     container.getAllProviderElements(),
+    //     unorderedEquals(<Object>[
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider),
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider.notifier)
+    //     ]),
+    //   );
+    //   expect(root.getAllProviderElements(), isEmpty);
+    // });
 
     test('when using provider.overrideWithProvider', () {
       final provider = ChangeNotifierProvider((ref) => ValueNotifier(0));
@@ -134,35 +149,33 @@ void main() {
         unorderedEquals(<Object>[
           isA<ProviderElementBase>()
               .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier)
         ]),
       );
       expect(root.getAllProviderElements(), isEmpty);
     });
   });
 
-  test('overriding with value listens to the ChangeNotifier', () {
-    final provider = ChangeNotifierProvider((ref) => ValueNotifier(0));
-    final notifier = ValueNotifier(42);
-    final listener = Listener<int>();
+  // test('overriding with value listens to the ChangeNotifier', () {
+  //   final provider = ChangeNotifierProvider((ref) => ValueNotifier(0));
+  //   final notifier = ValueNotifier(42);
+  //   final listener = Listener<int>();
 
-    final container = createContainer(
-      overrides: [provider.overrideWithValue(notifier)],
-    );
+  //   final container = createContainer(
+  //     overrides: [provider.overrideWithValue(notifier)],
+  //   );
 
-    container.listen<ValueNotifier<int>>(
-      provider,
-      (prev, value) => listener(prev?.value, value.value),
-    );
+  //   container.listen<ValueNotifier<int>>(
+  //     provider,
+  //     (prev, value) => listener(prev?.value, value.value),
+  //   );
 
-    expect(container.read(provider).value, 42);
-    expect(container.read(provider.notifier).value, 42);
+  //   expect(container.read(provider).value, 42);
+  //   expect(container.read(provider.notifier).value, 42);
 
-    notifier.value = 21;
+  //   notifier.value = 21;
 
-    verifyOnly(listener, listener(21, 21));
-  });
+  //   verifyOnly(listener, listener(21, 21));
+  // });
 
   test('refresh recreates the ChangeNotifier', () {
     final provider = ChangeNotifierProvider((ref) => ValueNotifier(0));
@@ -266,56 +279,56 @@ void main() {
     expect(callCount, 1);
   });
 
-  test(
-      'overrideWithValue listens to the notifier, support notifier change, and does not dispose of the notifier',
-      () async {
-    final provider = ChangeNotifierProvider((_) {
-      return TestNotifier('a');
-    });
-    final notifier = TestNotifier('b');
-    final notifier2 = TestNotifier('c');
-    final container = createContainer(overrides: [
-      provider.overrideWithValue(notifier),
-    ]);
-    addTearDown(container.dispose);
-
-    var callCount = 0;
-    final sub = container.listen(provider, (_, __) => callCount++);
-    final notifierSub = container.listen(provider.notifier, (_, __) {});
-
-    expect(sub.read(), notifier);
-    expect(callCount, 0);
-    expect(notifierSub.read(), notifier);
-    expect(notifier.hasListeners, true);
-
-    notifier.count++;
-
-    await container.pump();
-    expect(callCount, 1);
-
-    container.updateOverrides([
-      provider.overrideWithValue(notifier2),
-    ]);
-
-    await container.pump();
-    expect(callCount, 2);
-    expect(notifier.hasListeners, false);
-    expect(notifier2.hasListeners, true);
-    expect(notifier.mounted, true);
-    expect(notifierSub.read(), notifier2);
-
-    notifier2.count++;
-
-    await container.pump();
-    expect(callCount, 3);
-
-    container.dispose();
-
-    expect(callCount, 3);
-    expect(notifier2.hasListeners, false);
-    expect(notifier2.mounted, true);
-    expect(notifier.mounted, true);
-  });
+  // test(
+  //     'overrideWithValue listens to the notifier, support notifier change, and does not dispose of the notifier',
+  //     () async {
+  //   final provider = ChangeNotifierProvider((_) {
+  //     return TestNotifier('a');
+  //   });
+  //   final notifier = TestNotifier('b');
+  //   final notifier2 = TestNotifier('c');
+  //   final container = createContainer(overrides: [
+  //     provider.overrideWithValue(notifier),
+  //   ]);
+  //   addTearDown(container.dispose);
+
+  //   var callCount = 0;
+  //   final sub = container.listen(provider, (_, __) => callCount++);
+  //   final notifierSub = container.listen(provider.notifier, (_, __) {});
+
+  //   expect(sub.read(), notifier);
+  //   expect(callCount, 0);
+  //   expect(notifierSub.read(), notifier);
+  //   expect(notifier.hasListeners, true);
+
+  //   notifier.count++;
+
+  //   await container.pump();
+  //   expect(callCount, 1);
+
+  //   container.updateOverrides([
+  //     provider.overrideWithValue(notifier2),
+  //   ]);
+
+  //   await container.pump();
+  //   expect(callCount, 2);
+  //   expect(notifier.hasListeners, false);
+  //   expect(notifier2.hasListeners, true);
+  //   expect(notifier.mounted, true);
+  //   expect(notifierSub.read(), notifier2);
+
+  //   notifier2.count++;
+
+  //   await container.pump();
+  //   expect(callCount, 3);
+
+  //   container.dispose();
+
+  //   expect(callCount, 3);
+  //   expect(notifier2.hasListeners, false);
+  //   expect(notifier2.mounted, true);
+  //   expect(notifier.mounted, true);
+  // });
 
   test('ChangeNotifier can be auto-scoped', () async {
     final dep = Provider((ref) => 0);
diff --git a/packages/flutter_riverpod/test/providers/change_notifier/family_auto_dispose_change_notifier_provider_test.dart b/packages/flutter_riverpod/test/providers/change_notifier/family_auto_dispose_change_notifier_provider_test.dart
index cf9a9f18a2..483b7307c9 100644
--- a/packages/flutter_riverpod/test/providers/change_notifier/family_auto_dispose_change_notifier_provider_test.dart
+++ b/packages/flutter_riverpod/test/providers/change_notifier/family_auto_dispose_change_notifier_provider_test.dart
@@ -14,9 +14,6 @@ void main() {
 
       expect(provider(0).from, provider);
       expect(provider(0).argument, 0);
-
-      expect(provider(0).notifier.from, provider);
-      expect(provider(0).notifier.argument, 0);
     });
 
     test('support null ChangeNotifier', () {
@@ -46,8 +43,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
         expect(root.getAllProviderElementsInOrder(), isEmpty);
@@ -91,8 +86,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
       });
diff --git a/packages/flutter_riverpod/test/providers/change_notifier/family_change_notifier_provider_test.dart b/packages/flutter_riverpod/test/providers/change_notifier/family_change_notifier_provider_test.dart
index 27b99ad57f..c6f91c8843 100644
--- a/packages/flutter_riverpod/test/providers/change_notifier/family_change_notifier_provider_test.dart
+++ b/packages/flutter_riverpod/test/providers/change_notifier/family_change_notifier_provider_test.dart
@@ -13,9 +13,6 @@ void main() {
 
       expect(provider(0).from, provider);
       expect(provider(0).argument, 0);
-
-      expect(provider(0).notifier.from, provider);
-      expect(provider(0).notifier.argument, 0);
     });
 
     test('support null ChangeNotifier', () {
@@ -44,8 +41,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
         expect(root.getAllProviderElementsInOrder(), isEmpty);
@@ -88,8 +83,6 @@ void main() {
         unorderedEquals(<Object?>[
           isA<ProviderElementBase>()
               .having((e) => e.origin, 'origin', provider(0)),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider(0).notifier),
         ]),
       );
     });
diff --git a/packages/riverpod/test/framework/auto_dispose_test.dart b/packages/riverpod/test/framework/auto_dispose_test.dart
index 5fa6e6ba1f..3cbcd65bc3 100644
--- a/packages/riverpod/test/framework/auto_dispose_test.dart
+++ b/packages/riverpod/test/framework/auto_dispose_test.dart
@@ -331,20 +331,26 @@ final alwaysAlive = Provider((ref) {
       () async {
     final container = createContainer();
     var dependencyDisposeCount = 0;
-    final dependency = Provider.autoDispose((ref) {
-      ref.onDispose(() => dependencyDisposeCount++);
-      return 0;
-    });
+    final dependency = Provider.autoDispose(
+      name: 'dependency',
+      (ref) {
+        ref.onDispose(() => dependencyDisposeCount++);
+        return 0;
+      },
+    );
     final isDependendingOnDependency = StateProvider(
+      name: 'isDependendingOnDependency',
       (ref) => true,
-      name: 'foo',
     );
-    final provider = Provider.autoDispose((ref) {
-      ref.maintainState = true;
-      if (ref.watch(isDependendingOnDependency.state).state) {
-        ref.watch(dependency);
-      }
-    });
+    final provider = Provider.autoDispose(
+      name: 'provider',
+      (ref) {
+        ref.maintainState = true;
+        if (ref.watch(isDependendingOnDependency)) {
+          ref.watch(dependency);
+        }
+      },
+    );
 
     container.listen<void>(provider, (_, __) {});
 
@@ -354,8 +360,7 @@ final alwaysAlive = Provider((ref) {
       unorderedEquals(<Object>[
         dependency,
         provider,
-        isDependendingOnDependency.state,
-        isDependendingOnDependency.notifier,
+        isDependendingOnDependency,
       ]),
     );
 
@@ -367,8 +372,7 @@ final alwaysAlive = Provider((ref) {
       container.getAllProviderElements().map((e) => e.provider),
       unorderedEquals(<Object>[
         provider,
-        isDependendingOnDependency.state,
-        isDependendingOnDependency.notifier,
+        isDependendingOnDependency,
       ]),
     );
   });
diff --git a/packages/riverpod/test/framework/family_test.dart b/packages/riverpod/test/framework/family_test.dart
index cef6aac043..44aa51fc82 100644
--- a/packages/riverpod/test/framework/family_test.dart
+++ b/packages/riverpod/test/framework/family_test.dart
@@ -139,24 +139,12 @@ void main() {
           .having((p) => p.argument, 'argument', 0)
           .having((p) => p.from, 'from', family),
     );
-    expect(
-      family(0).notifier,
-      isA<AlwaysAliveProviderBase<Counter>>()
-          .having((p) => p.argument, 'argument', 0)
-          .having((p) => p.from, 'from', family),
-    );
     expect(
       family(1),
       isA<StateNotifierProvider<Counter, int>>()
           .having((p) => p.from, 'from', family)
           .having((p) => p.argument, 'argument', 1),
     );
-    expect(
-      family(1).notifier,
-      isA<AlwaysAliveProviderBase<Counter>>()
-          .having((p) => p.argument, 'argument', 1)
-          .having((p) => p.from, 'from', family),
-    );
   });
 
   test('family override', () {
diff --git a/packages/riverpod/test/framework/listen_test.dart b/packages/riverpod/test/framework/listen_test.dart
index a8ae7c3c79..0f4186c9a4 100644
--- a/packages/riverpod/test/framework/listen_test.dart
+++ b/packages/riverpod/test/framework/listen_test.dart
@@ -6,7 +6,6 @@ import 'package:test/expect.dart';
 import 'package:test/scaffolding.dart';
 
 import '../utils.dart';
-import 'uni_directional_test.dart';
 
 void main() {
   group('Ref.listenSelf', () {
@@ -605,7 +604,7 @@ void main() {
         final provider = Provider((ref) {
           sub = runZonedGuarded(
             () => ref.listen<int>(
-              dep.state.select((value) => value.state),
+              dep.select((value) => value),
               (prev, value) {
                 listener(prev, value);
                 if (isFirstCall) {
@@ -986,6 +985,43 @@ void main() {
       final listener = Listener<int>();
       final listener2 = Listener<int>();
 
+      final p = Provider((ref) {
+        ProviderSubscription<int>? a;
+        ref.listen<int>(provider, (prev, value) {
+          listener(prev, value);
+          a?.close();
+          a = null;
+        });
+
+        a = ref.listen<int>(provider, listener2);
+      });
+      container.read(p);
+
+      verifyZeroInteractions(listener);
+      verifyZeroInteractions(listener2);
+
+      container.read(provider.notifier).state++;
+
+      verifyInOrder([
+        listener(0, 1),
+        listener2(0, 1),
+      ]);
+
+      container.read(provider.notifier).state++;
+
+      verify(listener(1, 2)).called(1);
+      verifyNoMoreInteractions(listener2);
+    });
+
+    test(
+        'if a listener removes another provider.listen, the removed listener is still called (ProviderListenable)',
+        () {
+      final provider = StateProvider((ref) => 0);
+      final container = createContainer();
+
+      final listener = Listener<int>();
+      final listener2 = Listener<int>();
+
       final p = Provider((ref) {
         ProviderSubscription<StateController<int>>? a;
         ref.listen<StateController<int>>(provider.state, (prev, value) {
@@ -1014,7 +1050,13 @@ void main() {
 
       verify(listener(2, 2)).called(1);
       verifyNoMoreInteractions(listener2);
-    });
+      // TODO the problem is that ProviderListenable subscriptions are separate from
+      // ProviderElement subscriptions. So the ProviderElement.notifyListeners
+      // making a local copy of the list of subscriptions before notifying listeners
+      // does not apply to ProviderListenables
+      // Support for modifying listeners within a listener probably should be dropped anyway for performance.
+      // This would remove a list copy
+    }, skip: true);
 
     test(
         'if a listener adds a provider.listen, the new listener is not called immediately',
@@ -1046,7 +1088,7 @@ void main() {
     });
 
     test(
-        'if a listener removes another container.listen, the removed listener is still called',
+        'if a listener removes another container.listen, the removed listener is still called (ProviderListenable)',
         () {
       final provider = StateProvider((ref) => 0);
       final container = createContainer();
@@ -1068,17 +1110,57 @@ void main() {
       verifyZeroInteractions(listener);
       verifyZeroInteractions(listener2);
 
-      container.read(provider.state).state++;
+      container.read(provider.notifier).state++;
 
       verifyInOrder([
         listener(1, 1),
         listener2(1, 1),
       ]);
 
-      container.read(provider.state).state++;
+      container.read(provider.notifier).state++;
 
       verify(listener(2, 2)).called(1);
       verifyNoMoreInteractions(listener2);
+      // TODO the problem is that ProviderListenable subscriptions are separate from
+      // ProviderElement subscriptions. So the ProviderElement.notifyListeners
+      // making a local copy of the list of subscriptions before notifying listeners
+      // does not apply to ProviderListenables
+      // Support for modifying listeners within a listener probably should be dropped anyway for performance.
+      // This would remove a list copy
+    }, skip: true);
+
+    test(
+        'if a listener removes another container.listen, the removed listener is still called',
+        () {
+      final provider = StateProvider((ref) => 0);
+      final container = createContainer();
+
+      final listener = Listener<int>();
+      final listener2 = Listener<int>();
+
+      ProviderSubscription? a;
+      container.listen<int>(provider, (prev, value) {
+        listener(prev, value);
+        a?.close();
+        a = null;
+      });
+
+      a = container.listen<int>(provider, listener2);
+
+      verifyZeroInteractions(listener);
+      verifyZeroInteractions(listener2);
+
+      container.read(provider.notifier).state++;
+
+      verifyInOrder([
+        listener(0, 1),
+        listener2(0, 1),
+      ]);
+
+      container.read(provider.notifier).state++;
+
+      verify(listener(1, 2)).called(1);
+      verifyNoMoreInteractions(listener2);
     });
 
     group('fireImmediately', () {
@@ -1292,7 +1374,7 @@ void main() {
 
         final sub = runZonedGuarded(
           () => container.listen<int>(
-            provider.state.select((value) => value.state),
+            provider.select((value) => value),
             (prev, value) {
               listener(prev, value);
               if (isFirstCall) {
@@ -1541,7 +1623,7 @@ void main() {
       final listener = Listener<bool>();
 
       container.listen<bool>(
-        count.state.select((value) => value.state.isEven),
+        count.select((value) => value.isEven),
         listener,
         fireImmediately: true,
       );
diff --git a/packages/riverpod/test/framework/provider_container_test.dart b/packages/riverpod/test/framework/provider_container_test.dart
index 22cfc345db..0012b3fc00 100644
--- a/packages/riverpod/test/framework/provider_container_test.dart
+++ b/packages/riverpod/test/framework/provider_container_test.dart
@@ -3,7 +3,6 @@ import 'package:riverpod/riverpod.dart';
 import 'package:test/test.dart';
 
 import '../utils.dart';
-import 'uni_directional_test.dart';
 
 void main() {
   group('ProviderContainer', () {
@@ -206,6 +205,24 @@ void main() {
         'flushes listened-to providers even if they have no external listeners',
         () async {
       final dep = StateProvider((ref) => 0);
+      final provider = Provider((ref) => ref.watch(dep));
+      final another = StateProvider<int>((ref) {
+        ref.listen(provider, (prev, value) => ref.controller.state++);
+        return 0;
+      });
+      final container = createContainer();
+
+      expect(container.read(another), 0);
+
+      container.read(dep.notifier).state = 42;
+
+      expect(container.read(another), 1);
+    });
+
+    test(
+        'flushes listened-to providers even if they have no external listeners (with ProviderListenable)',
+        () async {
+      final dep = StateProvider((ref) => 0);
       final provider = Provider((ref) => ref.watch(dep.state).state);
       final another = StateProvider<int>((ref) {
         ref.listen(provider, (prev, value) => ref.controller.state++);
@@ -349,7 +366,7 @@ void main() {
           container.getAllProviderElements(),
           unorderedMatches(<Matcher>[
             isA<ProviderElementBase<int>>(),
-            isA<AutoDisposeProviderElementBase<int>>(),
+            isA<AutoDisposeProviderElementMixin<int>>(),
           ]),
         );
 
@@ -367,7 +384,7 @@ void main() {
           container.getAllProviderElements(),
           unorderedMatches(<Matcher>[
             isA<ProviderElementBase<int>>(),
-            isA<AutoDisposeProviderElementBase<int>>(),
+            isA<AutoDisposeProviderElementMixin<int>>(),
           ]),
         );
       });
diff --git a/packages/riverpod/test/framework/provider_element_test.dart b/packages/riverpod/test/framework/provider_element_test.dart
index 22eb485d83..d28c80f082 100644
--- a/packages/riverpod/test/framework/provider_element_test.dart
+++ b/packages/riverpod/test/framework/provider_element_test.dart
@@ -2,7 +2,7 @@ import 'dart:async';
 
 import 'package:mockito/mockito.dart';
 import 'package:riverpod/riverpod.dart';
-import 'package:riverpod/src/internals.dart' show ResultError;
+import 'package:riverpod/src/result.dart';
 import 'package:test/test.dart';
 
 import '../third_party/fake_async.dart';
@@ -1521,7 +1521,9 @@ void main() {
 
       final children = <ProviderElementBase>[];
 
-      container.readProviderElement(provider).visitChildren(children.add);
+      container
+          .readProviderElement(provider)
+          .visitChildren(elementVisitor: children.add, notifierVisitor: (_) {});
       expect(
         children,
         unorderedMatches(<Object>[
@@ -1548,7 +1550,9 @@ void main() {
 
       final children = <ProviderElementBase>[];
 
-      container.readProviderElement(provider).visitChildren(children.add);
+      container
+          .readProviderElement(provider)
+          .visitChildren(elementVisitor: children.add, notifierVisitor: (_) {});
       expect(
         children,
         unorderedMatches(<Object>[
diff --git a/packages/riverpod/test/framework/provider_observer_test.dart b/packages/riverpod/test/framework/provider_observer_test.dart
index 45689489e3..53767fd2d7 100644
--- a/packages/riverpod/test/framework/provider_observer_test.dart
+++ b/packages/riverpod/test/framework/provider_observer_test.dart
@@ -69,49 +69,49 @@ void main() {
         verifyNever(observer.providerDidFail(any, any, any, any));
       });
 
-      test(
-          'on scoped ProviderContainer, applies both child and ancestors observers',
-          () {
-        final provider = StateNotifierProvider<StateController<int>, int>(
-          (ref) => StateController(0),
-        );
-        final observer = ObserverMock();
-        final observer2 = ObserverMock();
-        final observer3 = ObserverMock();
-        final root = createContainer(observers: [observer]);
-        final mid = createContainer(
-          parent: root,
-          observers: [observer2],
-        );
-        final child = createContainer(
-          parent: mid,
-          overrides: [provider.overrideWithValue(StateController(42))],
-          observers: [observer3],
-        );
-
-        expect(child.read(provider), 42);
-        expect(mid.read(provider), 0);
-
-        clearInteractions(observer3);
-        clearInteractions(observer2);
-        clearInteractions(observer);
-
-        child.read(provider.notifier).state++;
-
-        verifyInOrder([
-          observer3.didUpdateProvider(provider, 42, 43, child),
-          observer2.didUpdateProvider(provider, 42, 43, child),
-          observer.didUpdateProvider(provider, 42, 43, child),
-        ]);
-
-        mid.read(provider.notifier).state++;
-
-        verify(observer.didUpdateProvider(provider, 0, 1, root)).called(1);
-
-        verifyNoMoreInteractions(observer3);
-        verifyNoMoreInteractions(observer2);
-        verifyNoMoreInteractions(observer);
-      });
+      // test(
+      //     'on scoped ProviderContainer, applies both child and ancestors observers',
+      //     () {
+      //   final provider = StateNotifierProvider<StateController<int>, int>(
+      //     (ref) => StateController(0),
+      //   );
+      //   final observer = ObserverMock();
+      //   final observer2 = ObserverMock();
+      //   final observer3 = ObserverMock();
+      //   final root = createContainer(observers: [observer]);
+      //   final mid = createContainer(
+      //     parent: root,
+      //     observers: [observer2],
+      //   );
+      //   final child = createContainer(
+      //     parent: mid,
+      //     overrides: [provider.overrideWithValue(StateController(42))],
+      //     observers: [observer3],
+      //   );
+
+      //   expect(child.read(provider), 42);
+      //   expect(mid.read(provider), 0);
+
+      //   clearInteractions(observer3);
+      //   clearInteractions(observer2);
+      //   clearInteractions(observer);
+
+      //   child.read(provider.notifier).state++;
+
+      //   verifyInOrder([
+      //     observer3.didUpdateProvider(provider, 42, 43, child),
+      //     observer2.didUpdateProvider(provider, 42, 43, child),
+      //     observer.didUpdateProvider(provider, 42, 43, child),
+      //   ]);
+
+      //   mid.read(provider.notifier).state++;
+
+      //   verify(observer.didUpdateProvider(provider, 0, 1, root)).called(1);
+
+      //   verifyNoMoreInteractions(observer3);
+      //   verifyNoMoreInteractions(observer2);
+      //   verifyNoMoreInteractions(observer);
+      // });
 
       test('handles computed provider update', () async {
         final observer = ObserverMock();
@@ -150,84 +150,84 @@ void main() {
         ).called(1);
       });
 
-      test('didUpdateProviders', () {
-        final observer = ObserverMock();
-        final observer2 = ObserverMock();
-        final provider = StateNotifierProvider<Counter, int>((_) => Counter());
-        final counter = Counter();
-        final container = createContainer(
-          overrides: [
-            provider.overrideWithValue(counter),
-          ],
-          observers: [observer, observer2],
-        );
-        final listener = Listener<int>();
-
-        container.listen(provider, listener, fireImmediately: true);
-
-        verify(listener(null, 0)).called(1);
-        verifyNoMoreInteractions(listener);
-        verifyInOrder([
-          observer.didAddProvider(
-            provider.notifier,
-            counter,
-            container,
-          ),
-          observer2.didAddProvider(provider.notifier, counter, container),
-          observer.didAddProvider(provider, 0, container),
-          observer2.didAddProvider(provider, 0, container),
-        ]);
-        verifyNoMoreInteractions(observer);
-        verifyNoMoreInteractions(observer2);
-
-        counter.increment();
-
-        verifyInOrder([
-          listener(0, 1),
-          observer.didUpdateProvider(provider, 0, 1, container),
-          observer2.didUpdateProvider(provider, 0, 1, container),
-        ]);
-        verifyNoMoreInteractions(listener);
-        verifyNoMoreInteractions(observer);
-        verifyNoMoreInteractions(observer2);
-      });
-
-      test('guards didUpdateProviders', () {
-        final observer = ObserverMock();
-        when(observer.didUpdateProvider(any, any, any, any))
-            .thenThrow('error1');
-        final observer2 = ObserverMock();
-        when(observer2.didUpdateProvider(any, any, any, any))
-            .thenThrow('error2');
-        final observer3 = ObserverMock();
-        final provider = StateNotifierProvider<Counter, int>((_) => Counter());
-        final counter = Counter();
-        final container = createContainer(
-          overrides: [
-            provider.overrideWithValue(counter),
-          ],
-          observers: [observer, observer2, observer3],
-        );
-
-        container.read(provider);
-
-        clearInteractions(observer);
-        clearInteractions(observer2);
-        clearInteractions(observer3);
-
-        final errors = <Object>[];
-        runZonedGuarded(counter.increment, (err, stack) => errors.add(err));
-
-        expect(errors, ['error1', 'error2']);
-        verifyInOrder([
-          observer.didUpdateProvider(provider, 0, 1, container),
-          observer2.didUpdateProvider(provider, 0, 1, container),
-          observer3.didUpdateProvider(provider, 0, 1, container),
-        ]);
-        verifyNoMoreInteractions(observer);
-        verifyNoMoreInteractions(observer2);
-        verifyNoMoreInteractions(observer3);
-      });
+      // test('didUpdateProviders', () {
+      //   final observer = ObserverMock();
+      //   final observer2 = ObserverMock();
+      //   final provider = StateNotifierProvider<Counter, int>((_) => Counter());
+      //   final counter = Counter();
+      //   final container = createContainer(
+      //     overrides: [
+      //       provider.overrideWithValue(counter),
+      //     ],
+      //     observers: [observer, observer2],
+      //   );
+      //   final listener = Listener<int>();
+
+      //   container.listen(provider, listener, fireImmediately: true);
+
+      //   verify(listener(null, 0)).called(1);
+      //   verifyNoMoreInteractions(listener);
+      //   verifyInOrder([
+      //     observer.didAddProvider(
+      //       provider.notifier,
+      //       counter,
+      //       container,
+      //     ),
+      //     observer2.didAddProvider(provider.notifier, counter, container),
+      //     observer.didAddProvider(provider, 0, container),
+      //     observer2.didAddProvider(provider, 0, container),
+      //   ]);
+      //   verifyNoMoreInteractions(observer);
+      //   verifyNoMoreInteractions(observer2);
+
+      //   counter.increment();
+
+      //   verifyInOrder([
+      //     listener(0, 1),
+      //     observer.didUpdateProvider(provider, 0, 1, container),
+      //     observer2.didUpdateProvider(provider, 0, 1, container),
+      //   ]);
+      //   verifyNoMoreInteractions(listener);
+      //   verifyNoMoreInteractions(observer);
+      //   verifyNoMoreInteractions(observer2);
+      // });
+
+      // test('guards didUpdateProviders', () {
+      //   final observer = ObserverMock();
+      //   when(observer.didUpdateProvider(any, any, any, any))
+      //       .thenThrow('error1');
+      //   final observer2 = ObserverMock();
+      //   when(observer2.didUpdateProvider(any, any, any, any))
+      //       .thenThrow('error2');
+      //   final observer3 = ObserverMock();
+      //   final provider = StateNotifierProvider<Counter, int>((_) => Counter());
+      //   final counter = Counter();
+      //   final container = createContainer(
+      //     overrides: [
+      //       provider.overrideWithValue(counter),
+      //     ],
+      //     observers: [observer, observer2, observer3],
+      //   );
+
+      //   container.read(provider);
+
+      //   clearInteractions(observer);
+      //   clearInteractions(observer2);
+      //   clearInteractions(observer3);
+
+      //   final errors = <Object>[];
+      //   runZonedGuarded(counter.increment, (err, stack) => errors.add(err));
+
+      //   expect(errors, ['error1', 'error2']);
+      //   verifyInOrder([
+      //     observer.didUpdateProvider(provider, 0, 1, container),
+      //     observer2.didUpdateProvider(provider, 0, 1, container),
+      //     observer3.didUpdateProvider(provider, 0, 1, container),
+      //   ]);
+      //   verifyNoMoreInteractions(observer);
+      //   verifyNoMoreInteractions(observer2);
+      //   verifyNoMoreInteractions(observer3);
+      // });
 
       test("Computed don't call didUpdateProviders when value doesn't change",
           () async {
@@ -498,7 +498,6 @@ void main() {
 
       verifyInOrder([
         observer.didDisposeProvider(provider, container),
-        observer.didDisposeProvider(provider.notifier, container),
       ]);
       verifyNoMoreInteractions(observer);
     });
@@ -519,7 +518,6 @@ void main() {
 
       verifyInOrder([
         observer.didDisposeProvider(provider, container),
-        observer.didDisposeProvider(provider.notifier, container),
       ]);
       verifyNoMoreInteractions(observer);
     });
diff --git a/packages/riverpod/test/framework/select_async_test.dart b/packages/riverpod/test/framework/select_async_test.dart
index 09c8fb274b..b0e26b32ea 100644
--- a/packages/riverpod/test/framework/select_async_test.dart
+++ b/packages/riverpod/test/framework/select_async_test.dart
@@ -98,7 +98,7 @@ void main() {
 
   test('handles fireImmediately: true on AsyncData', () async {
     final container = createContainer();
-    final provider = Provider((ref) => const AsyncData(0));
+    final provider = FutureProvider((ref) => 0);
     final listener = Listener<Future<bool>>();
 
     container.listen(
@@ -115,7 +115,7 @@ void main() {
 
   test('handles fireImmediately: true on AsyncError', () async {
     final container = createContainer();
-    final provider = Provider((ref) => const AsyncError<int>(0));
+    final provider = FutureProvider<int>((ref) => throw StateError('0'));
     final listener = Listener<Future<bool>>();
 
     container.listen(
@@ -127,7 +127,7 @@ void main() {
     final result = verify(listener(argThat(isNull), captureAny)).captured.single
         as Future<bool>;
     verifyNoMoreInteractions(listener);
-    await expectLater(result, throwsA(0));
+    await expectLater(result, throwsStateError);
   });
 
   test('handles fireImmediately: false', () async {
@@ -148,7 +148,7 @@ void main() {
       'catching errors in the future is not necessary if the error is coming from AsyncError',
       () async {
     final container = createContainer();
-    final provider = Provider((ref) => const AsyncError<int>(0));
+    final provider = FutureProvider<int>((ref) => throw StateError('err'));
 
     container.listen(
       provider.selectAsync((data) => data.isEven),
@@ -162,7 +162,14 @@ void main() {
 
   test('handles multiple AsyncLoading at once then data', () async {
     final container = createContainer();
-    final provider = StateProvider((ref) => const AsyncValue<int>.loading());
+    late FutureProviderRef<int> ref;
+    final provider = FutureProvider<int>((r) {
+      ref = r;
+      final completer = Completer<int>();
+      ref.onDispose(() => completer.complete(42));
+
+      return completer.future;
+    });
 
     final sub = container.listen(
       provider.selectAsync((data) => data + 40),
@@ -171,13 +178,13 @@ void main() {
 
     expect(sub.read(), completion(42));
 
-    container.read(provider.notifier).state = const AsyncLoading<int>()
+    ref.state = const AsyncLoading<int>()
         .copyWithPrevious(const AsyncValue<int>.data(0));
-    container.read(provider.notifier).state = const AsyncLoading<int>()
+    ref.state = const AsyncLoading<int>()
         .copyWithPrevious(const AsyncError<int>('err'));
-    container.read(provider.notifier).state = const AsyncLoading<int>();
+    ref.state = const AsyncLoading<int>();
 
-    container.read(provider.notifier).state = const AsyncData(2);
+    ref.state = const AsyncData(2);
 
     // the previous unawaited `completion` should resolve with 2+40
   });
@@ -263,4 +270,37 @@ void main() {
     expect(await container.read(b.future), 1);
     expect(buildCount, 2);
   });
+
+  group('Supports ProviderContainer.read', () {
+    test('and resolves with data', () async {
+      final container = createContainer();
+      final provider = FutureProvider((ref) async => 0);
+
+      expect(
+        container.read(provider.selectAsync((data) => data.toString())),
+        completion('0'),
+      );
+    });
+
+    test('resolves with error', () async {
+      final container = createContainer();
+      final provider =
+          FutureProvider<int>((ref) async => throw StateError('err'));
+
+      expect(
+        container.read(provider.selectAsync((data) => data)),
+        throwsStateError,
+      );
+    });
+
+    test('emits exceptions inside selectors as Future.error', () async {
+      final container = createContainer();
+      final provider = FutureProvider<int>((ref) async => 42);
+
+      expect(
+        container.read(provider.selectAsync((data) => throw StateError('err'))),
+        throwsStateError,
+      );
+    });
+  });
 }
diff --git a/packages/riverpod/test/framework/uni_directional_test.dart b/packages/riverpod/test/framework/uni_directional_test.dart
index faca09c6ef..67c88631c8 100644
--- a/packages/riverpod/test/framework/uni_directional_test.dart
+++ b/packages/riverpod/test/framework/uni_directional_test.dart
@@ -4,8 +4,6 @@ import 'package:test/test.dart';
 
 import '../utils.dart';
 
-final isAssertionError = isA<AssertionError>();
-
 void main() {
   late ProviderContainer container;
   setUp(() {
diff --git a/packages/riverpod/test/legacy/framework2/framework_test.dart b/packages/riverpod/test/legacy/framework2/framework_test.dart
index f66f803417..4934f15034 100644
--- a/packages/riverpod/test/legacy/framework2/framework_test.dart
+++ b/packages/riverpod/test/legacy/framework2/framework_test.dart
@@ -255,9 +255,15 @@ void main() {
 
     expect(sub.read(), '0');
     var firstDependents = <ProviderElementBase>[];
-    firstElement.visitChildren(firstDependents.add);
+    firstElement.visitChildren(
+      elementVisitor: firstDependents.add,
+      notifierVisitor: (_) {},
+    );
     var secondDependents = <ProviderElementBase>[];
-    secondElement.visitChildren(secondDependents.add);
+    secondElement.visitChildren(
+      elementVisitor: secondDependents.add,
+      notifierVisitor: (_) {},
+    );
 
     expect(firstDependents, [computedElement]);
     expect(firstElement.hasListeners, true);
@@ -268,34 +274,40 @@ void main() {
     expect(sub.read(), 'fallback');
 
     firstDependents = <ProviderElementBase>[];
-    firstElement.visitChildren(firstDependents.add);
+    firstElement.visitChildren(
+      elementVisitor: firstDependents.add,
+      notifierVisitor: (_) {},
+    );
     secondDependents = <ProviderElementBase>[];
-    secondElement.visitChildren(secondDependents.add);
+    secondElement.visitChildren(
+      elementVisitor: secondDependents.add,
+      notifierVisitor: (_) {},
+    );
     expect(firstDependents, [computedElement]);
     expect(firstElement.hasListeners, true);
     expect(secondDependents, <ProviderElement>[]);
     expect(secondElement.hasListeners, false);
   });
 
-  group('overrideWithValue', () {
-    test('synchronously overrides the value', () {
-      var callCount = 0;
-      final provider = FutureProvider((ref) async {
-        callCount++;
-        return 0;
-      });
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+  // group('overrideWithValue', () {
+  //   test('synchronously overrides the value', () {
+  //     var callCount = 0;
+  //     final provider = FutureProvider((ref) async {
+  //       callCount++;
+  //       return 0;
+  //     });
+  //     final container = createContainer(overrides: [
+  //       provider.overrideWithValue(const AsyncValue.data(42)),
+  //     ]);
 
-      addTearDown(container.dispose);
+  //     addTearDown(container.dispose);
 
-      final sub = container.listen(provider, (_, __) {});
+  //     final sub = container.listen(provider, (_, __) {});
 
-      expect(callCount, 0);
-      expect(sub.read(), const AsyncValue.data(42));
-    });
-  });
+  //     expect(callCount, 0);
+  //     expect(sub.read(), const AsyncValue.data(42));
+  //   });
+  // });
 
   test('remove dependencies on dispose', () async {
     final first = StateProvider((ref) => 0);
@@ -308,7 +320,10 @@ void main() {
 
     expect(sub.read(), 0);
     var firstDependents = <ProviderElementBase>[];
-    firstElement.visitChildren(firstDependents.add);
+    firstElement.visitChildren(
+      elementVisitor: firstDependents.add,
+      notifierVisitor: (_) {},
+    );
     expect(firstDependents, {computedElement});
     expect(firstElement.hasListeners, true);
 
@@ -316,7 +331,10 @@ void main() {
     await container.pump();
 
     firstDependents = <ProviderElementBase>[];
-    firstElement.visitChildren(firstDependents.add);
+    firstElement.visitChildren(
+      elementVisitor: firstDependents.add,
+      notifierVisitor: (_) {},
+    );
     expect(firstDependents, <ProviderElement>{});
     expect(firstElement.hasListeners, false);
   });
@@ -561,7 +579,7 @@ void main() {
     });
 
     test(
-        'retrying a provider already marked as needing to update do not create the value twice',
+        'refreshing a provider already marked as needing to update do not create the value twice',
         () async {
       var future = Future.value(42);
       var callCount = 0;
@@ -574,6 +592,7 @@ void main() {
       final container = createContainer();
 
       container.refresh(provider);
+
       expect(callCount, 1);
 
       container.read(dep.state).state++;
@@ -581,6 +600,7 @@ void main() {
 
       expect(callCount, 1);
       container.refresh(provider);
+
       expect(callCount, 2);
       await expectLater(container.read(provider.future), completion(21));
       expect(callCount, 2);
diff --git a/packages/riverpod/test/matchers.dart b/packages/riverpod/test/matchers.dart
index cca2bf38bf..7eb97acfd2 100644
--- a/packages/riverpod/test/matchers.dart
+++ b/packages/riverpod/test/matchers.dart
@@ -1,4 +1,4 @@
-import 'package:riverpod/src/provider.dart';
+import 'package:riverpod/src/devtool.dart';
 import 'package:test/test.dart';
 
 Matcher isPostEventCall(Object kind, Object? event) {
diff --git a/packages/riverpod/test/providers/future_provider/auto_dispose_family_future_provider_test.dart b/packages/riverpod/test/providers/future_provider/auto_dispose_family_future_provider_test.dart
index a49624a5ae..f39562937d 100644
--- a/packages/riverpod/test/providers/future_provider/auto_dispose_family_future_provider_test.dart
+++ b/packages/riverpod/test/providers/future_provider/auto_dispose_family_future_provider_test.dart
@@ -47,12 +47,6 @@ void main() {
 
     expect(provider(0).from, provider);
     expect(provider(0).argument, 0);
-
-    expect(provider(0).future.from, provider);
-    expect(provider(0).future.argument, 0);
-
-    expect(provider(0).stream.from, provider);
-    expect(provider(0).stream.argument, 0);
   });
 
   group('scoping an override overrides all the associated subproviders', () {
@@ -67,8 +61,6 @@ void main() {
       expect(container.getAllProviderElementsInOrder(), [
         isA<ProviderElementBase>()
             .having((e) => e.origin, 'origin', provider(0)),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider(0).future),
       ]);
       expect(root.getAllProviderElementsInOrder(), isEmpty);
     });
@@ -108,8 +100,6 @@ void main() {
       expect(container.getAllProviderElementsInOrder(), [
         isA<ProviderElementBase>()
             .having((e) => e.origin, 'origin', provider(0)),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider(0).future),
       ]);
     });
   });
diff --git a/packages/riverpod/test/providers/future_provider/auto_dispose_future_provider_test.dart b/packages/riverpod/test/providers/future_provider/auto_dispose_future_provider_test.dart
index 81c0c8882b..cb7cbd8f78 100644
--- a/packages/riverpod/test/providers/future_provider/auto_dispose_future_provider_test.dart
+++ b/packages/riverpod/test/providers/future_provider/auto_dispose_future_provider_test.dart
@@ -238,27 +238,25 @@ void main() {
       expect(root.getAllProviderElementsInOrder(), isEmpty);
       expect(container.getAllProviderElementsInOrder(), [
         isA<ProviderElementBase>().having((e) => e.origin, 'origin', provider),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider.future)
       ]);
     });
 
-    test('when using provider.overrideWithValue', () async {
-      final provider = FutureProvider.autoDispose((ref) async => 0);
-      final root = createContainer();
-      final container = createContainer(parent: root, overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
-
-      expect(await container.read(provider.future), 42);
-      expect(container.read(provider), const AsyncValue.data(42));
-      expect(root.getAllProviderElementsInOrder(), isEmpty);
-      expect(container.getAllProviderElementsInOrder(), [
-        isA<ProviderElementBase>().having((e) => e.origin, 'origin', provider),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider.future)
-      ]);
-    });
+    // test('when using provider.overrideWithValue', () async {
+    //   final provider = FutureProvider.autoDispose((ref) async => 0);
+    //   final root = createContainer();
+    //   final container = createContainer(parent: root, overrides: [
+    //     provider.overrideWithValue(const AsyncValue.data(42)),
+    //   ]);
+
+    //   expect(await container.read(provider.future), 42);
+    //   expect(container.read(provider), const AsyncValue.data(42));
+    //   expect(root.getAllProviderElementsInOrder(), isEmpty);
+    //   expect(container.getAllProviderElementsInOrder(), [
+    //     isA<ProviderElementBase>().having((e) => e.origin, 'origin', provider),
+    //     isA<ProviderElementBase>()
+    //         .having((e) => e.origin, 'origin', provider.future)
+    //   ]);
+    // });
 
     test('when using provider.overrideWithProvider', () async {
       final provider = FutureProvider.autoDispose((ref) async => 0);
@@ -272,8 +270,6 @@ void main() {
       expect(root.getAllProviderElementsInOrder(), isEmpty);
       expect(container.getAllProviderElementsInOrder(), [
         isA<ProviderElementBase>().having((e) => e.origin, 'origin', provider),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider.future)
       ]);
     });
   });
diff --git a/packages/riverpod/test/providers/future_provider/family_future_provider_test.dart b/packages/riverpod/test/providers/future_provider/family_future_provider_test.dart
index 7c670a86b0..b6c87799f4 100644
--- a/packages/riverpod/test/providers/future_provider/family_future_provider_test.dart
+++ b/packages/riverpod/test/providers/future_provider/family_future_provider_test.dart
@@ -9,12 +9,6 @@ void main() {
 
     expect(provider(0).from, provider);
     expect(provider(0).argument, 0);
-
-    expect(provider(0).future.from, provider);
-    expect(provider(0).future.argument, 0);
-
-    expect(provider(0).stream.from, provider);
-    expect(provider(0).stream.argument, 0);
   });
 
   group('scoping an override overrides all the associated subproviders', () {
@@ -28,8 +22,6 @@ void main() {
       expect(container.getAllProviderElementsInOrder(), [
         isA<ProviderElementBase>()
             .having((e) => e.origin, 'origin', provider(0)),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider(0).future),
       ]);
       expect(root.getAllProviderElementsInOrder(), isEmpty);
     });
@@ -66,8 +58,6 @@ void main() {
       expect(container.getAllProviderElementsInOrder(), [
         isA<ProviderElementBase>()
             .having((e) => e.origin, 'origin', provider(0)),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider(0).future),
       ]);
     });
   });
diff --git a/packages/riverpod/test/providers/future_provider/future_provider_test.dart b/packages/riverpod/test/providers/future_provider/future_provider_test.dart
index 88dda01e47..bf09fc9fc3 100644
--- a/packages/riverpod/test/providers/future_provider/future_provider_test.dart
+++ b/packages/riverpod/test/providers/future_provider/future_provider_test.dart
@@ -144,7 +144,7 @@ void main() {
   });
 
   test(
-      '.stream does not update dependents if the created stream did not change',
+      '.future does not update dependents if the created future did not change',
       () async {
     final container = createContainer();
     final dep = StateProvider((ref) => 0);
@@ -163,11 +163,6 @@ void main() {
     await container.pump();
 
     verifyNoMoreInteractions(listener);
-
-    // No value were emitted, so the future will fail. Catching the error to
-    // avoid false positive.
-    // ignore: unawaited_futures, avoid_types_on_closure_parameters
-    container.read(provider.future).catchError((Object _) => 0);
   });
 
   group('scoping an override overrides all the associated subproviders', () {
@@ -181,27 +176,25 @@ void main() {
       expect(root.getAllProviderElementsInOrder(), isEmpty);
       expect(container.getAllProviderElementsInOrder(), [
         isA<ProviderElementBase>().having((e) => e.origin, 'origin', provider),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider.future)
       ]);
     });
 
-    test('when using provider.overrideWithValue', () async {
-      final provider = FutureProvider((ref) async => 0);
-      final root = createContainer();
-      final container = createContainer(parent: root, overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
-
-      expect(await container.read(provider.future), 42);
-      expect(container.read(provider), const AsyncValue.data(42));
-      expect(root.getAllProviderElementsInOrder(), isEmpty);
-      expect(container.getAllProviderElementsInOrder(), [
-        isA<ProviderElementBase>().having((e) => e.origin, 'origin', provider),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider.future)
-      ]);
-    });
+    // test('when using provider.overrideWithValue', () async {
+    //   final provider = FutureProvider((ref) async => 0);
+    //   final root = createContainer();
+    //   final container = createContainer(parent: root, overrides: [
+    //     provider.overrideWithValue(const AsyncValue.data(42)),
+    //   ]);
+
+    //   expect(await container.read(provider.future), 42);
+    //   expect(container.read(provider), const AsyncValue.data(42));
+    //   expect(root.getAllProviderElementsInOrder(), isEmpty);
+    //   expect(container.getAllProviderElementsInOrder(), [
+    //     isA<ProviderElementBase>().having((e) => e.origin, 'origin', provider),
+    //     isA<ProviderElementBase>()
+    //         .having((e) => e.origin, 'origin', provider.future)
+    //   ]);
+    // });
 
     test('when using provider.overrideWithProvider', () async {
       final provider = FutureProvider((ref) async => 0);
@@ -215,30 +208,28 @@ void main() {
       expect(root.getAllProviderElementsInOrder(), isEmpty);
       expect(container.getAllProviderElementsInOrder(), [
         isA<ProviderElementBase>().having((e) => e.origin, 'origin', provider),
-        isA<ProviderElementBase>()
-            .having((e) => e.origin, 'origin', provider.future)
       ]);
     });
   });
 
-  test(
-      'when overridden with an error but provider.future is not listened to, it should not emit an error to the zone',
-      () async {
-    final error = Error();
-    final future = FutureProvider<int>((ref) async => 0);
+  // test(
+  //     'when overridden with an error but provider.future is not listened to, it should not emit an error to the zone',
+  //     () async {
+  //   final error = Error();
+  //   final future = FutureProvider<int>((ref) async => 0);
 
-    final container = createContainer(overrides: [
-      future.overrideWithValue(AsyncValue.error(error)),
-    ]);
-    addTearDown(container.dispose);
+  //   final container = createContainer(overrides: [
+  //     future.overrideWithValue(AsyncValue.error(error)),
+  //   ]);
+  //   addTearDown(container.dispose);
 
-    expect(
-      container.read(future),
-      AsyncValue<int>.error(error),
-    );
+  //   expect(
+  //     container.read(future),
+  //     AsyncValue<int>.error(error),
+  //   );
 
-    // the test will naturally fail if a non-caught future is created
-  });
+  //   // the test will naturally fail if a non-caught future is created
+  // });
 
   test('throwing inside "create" result in an AsyncValue.error', () {
     // ignore: only_throw_errors
@@ -352,42 +343,26 @@ void main() {
       await expectLater(container.read(dependent), completion(21));
       expect(callCount, 2);
     });
-
-    test('.name is the listened-to name.future', () {
-      expect(
-        FutureProvider((ref) async {}, name: 'hey').future.name,
-        'hey.future',
-      );
-      expect(
-        FutureProvider((ref) async {}).future.name,
-        null,
-      );
-    });
   });
 
   group('FutureProvider.autoDispose().future', () {
-    test('.name is the listened-to name.future', () {
-      expect(
-        FutureProvider.autoDispose((ref) async {}, name: 'hey').future.name,
-        'hey.future',
-      );
-      expect(
-        FutureProvider.autoDispose((ref) async {}).future.name,
-        null,
-      );
-    });
-
     test('update dependents when the future changes', () async {
-      final futureProvider = StateProvider((ref) => Future.value(42));
+      final futureProvider = StateProvider(
+        (ref) => Future.value(42),
+        name: 'futureProvider',
+      );
       // a FutureProvider that can rebuild with a new future
       final provider = FutureProvider.autoDispose(
-          (ref) => ref.watch(futureProvider.state).state);
+        name: 'provider',
+        (ref) => ref.watch(futureProvider.state).state,
+      );
       var callCount = 0;
-      final dependent = Provider.autoDispose((ref) {
+      final dependent = Provider.autoDispose(name: 'dependent', (ref) {
         callCount++;
         return ref.watch(provider.future);
       });
       final container = createContainer();
+
       final futureController = container.read(futureProvider.state);
 
       final sub = container.listen(dependent, (_, __) {});
@@ -466,10 +441,6 @@ void main() {
     verifyOnly(listener, listener(null, const AsyncValue<String>.loading()));
     completer.complete(42);
 
-    verifyNoMoreInteractions(listener);
-
-    await container.pump();
-
     verifyOnly(
       listener,
       listener(const AsyncValue.loading(), const AsyncValue.data('21 42')),
@@ -498,285 +469,285 @@ void main() {
     verifyNoMoreInteractions(listener);
   });
 
-  group('mock as value', () {
-    test('value immediately then other value', () async {
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+  // group('mock as value', () {
+  //   test('value immediately then other value', () async {
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider.overrideWithValue(const AsyncValue.data(42)),
+  //     ]);
 
-      await expectLater(
-        container.read(provider.future),
-        completion(42),
-      );
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       completion(42),
+  //     );
 
-      final sub = container.listen(provider, (_, __) {});
+  //     final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue.data(42));
+  //     expect(sub.read(), const AsyncValue.data(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(21)),
-      ]);
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(const AsyncValue.data(21)),
+  //     ]);
 
-      await expectLater(
-        container.read(provider.future),
-        completion(21),
-      );
-      expect(sub.read(), const AsyncValue.data(21));
-    });
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       completion(21),
+  //     );
+  //     expect(sub.read(), const AsyncValue.data(21));
+  //   });
 
-    test('value immediately then error', () async {
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+  //   test('value immediately then error', () async {
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider.overrideWithValue(const AsyncValue.data(42)),
+  //     ]);
 
-      await expectLater(
-        container.read(provider.future),
-        completion(42),
-      );
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       completion(42),
+  //     );
 
-      final sub = container.listen(provider, (_, __) {});
+  //     final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue.data(42));
+  //     expect(sub.read(), const AsyncValue.data(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.error(21)),
-      ]);
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(const AsyncValue.error(21)),
+  //     ]);
 
-      await expectLater(
-        container.read(provider.future),
-        throwsA(21),
-      );
-      expect(
-        sub.read(),
-        const AsyncValue<int>.error(21).copyWithPrevious(const AsyncData(42)),
-      );
-    });
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       throwsA(21),
+  //     );
+  //     expect(
+  //       sub.read(),
+  //       const AsyncValue<int>.error(21).copyWithPrevious(const AsyncData(42)),
+  //     );
+  //   });
 
-    test('value immediately then loading', () async {
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+  //   test('value immediately then loading', () async {
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider.overrideWithValue(const AsyncValue.data(42)),
+  //     ]);
 
-      final future = container.read(provider.future);
+  //     final future = container.read(provider.future);
 
-      await expectLater(
-        future,
-        completion(42),
-      );
+  //     await expectLater(
+  //       future,
+  //       completion(42),
+  //     );
 
-      final sub = container.listen(provider, (_, __) {});
+  //     final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue<int>.data(42));
+  //     expect(sub.read(), const AsyncValue<int>.data(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.loading()),
-      ]);
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(const AsyncValue.loading()),
+  //     ]);
 
-      expect(container.read(provider.future), isNot(future));
-      expect(
-        sub.read(),
-        const AsyncLoading<int>()
-            .copyWithPrevious(const AsyncValue<int>.data(42)),
-      );
-    });
+  //     expect(container.read(provider.future), isNot(future));
+  //     expect(
+  //       sub.read(),
+  //       const AsyncLoading<int>()
+  //           .copyWithPrevious(const AsyncValue<int>.data(42)),
+  //     );
+  //   });
 
-    test('loading immediately then value', () async {
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.loading()),
-      ]);
+  //   test('loading immediately then value', () async {
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider.overrideWithValue(const AsyncValue.loading()),
+  //     ]);
 
-      final future = container.read(provider.future);
+  //     final future = container.read(provider.future);
 
-      final sub = container.listen(provider, (_, __) {});
+  //     final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue<int>.loading());
+  //     expect(sub.read(), const AsyncValue<int>.loading());
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(const AsyncValue.data(42)),
+  //     ]);
 
-      expect(sub.read(), const AsyncValue<int>.data(42));
+  //     expect(sub.read(), const AsyncValue<int>.data(42));
 
-      await expectLater(future, completion(42));
-    });
+  //     await expectLater(future, completion(42));
+  //   });
 
-    test('loading immediately then error', () async {
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.loading()),
-      ]);
+  //   test('loading immediately then error', () async {
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider.overrideWithValue(const AsyncValue.loading()),
+  //     ]);
 
-      final future = container.read(provider.future);
+  //     final future = container.read(provider.future);
 
-      final sub = container.listen(provider, (_, __) {});
+  //     final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue<int>.loading());
+  //     expect(sub.read(), const AsyncValue<int>.loading());
 
-      final stackTrace = StackTrace.current;
+  //     final stackTrace = StackTrace.current;
 
-      container.updateOverrides([
-        provider
-            .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
-      ]);
+  //     container.updateOverrides([
+  //       provider
+  //           .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
+  //     ]);
 
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+  //     expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
 
-      await expectLater(future, throwsA(42));
-    });
+  //     await expectLater(future, throwsA(42));
+  //   });
 
-    test('loading immediately then loading', () async {
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.loading()),
-      ]);
-      final listener = Listener<AsyncValue<int>>();
+  //   test('loading immediately then loading', () async {
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider.overrideWithValue(const AsyncValue.loading()),
+  //     ]);
+  //     final listener = Listener<AsyncValue<int>>();
 
-      final future = container.read(provider.future);
+  //     final future = container.read(provider.future);
 
-      container.listen(provider, listener, fireImmediately: true);
+  //     container.listen(provider, listener, fireImmediately: true);
 
-      verifyOnly(listener, listener(null, const AsyncValue<int>.loading()));
+  //     verifyOnly(listener, listener(null, const AsyncValue<int>.loading()));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.loading()),
-      ]);
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(const AsyncValue.loading()),
+  //     ]);
 
-      verifyNoMoreInteractions(listener);
+  //     verifyNoMoreInteractions(listener);
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(const AsyncValue.data(42)),
+  //     ]);
 
-      verifyOnly(
-        listener,
-        listener(const AsyncValue.loading(), const AsyncValue.data(42)),
-      );
-      await expectLater(future, completion(42));
-    });
+  //     verifyOnly(
+  //       listener,
+  //       listener(const AsyncValue.loading(), const AsyncValue.data(42)),
+  //     );
+  //     await expectLater(future, completion(42));
+  //   });
 
-    test('error immediately then different error', () async {
-      final stackTrace = StackTrace.current;
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider
-            .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
-      ]);
+  //   test('error immediately then different error', () async {
+  //     final stackTrace = StackTrace.current;
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider
+  //           .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
+  //     ]);
 
-      await expectLater(
-        container.read(provider.future),
-        throwsA(42),
-      );
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       throwsA(42),
+  //     );
 
-      final sub = container.listen(provider, (_, __) {});
+  //     final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+  //     expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
 
-      container.updateOverrides([
-        provider
-            .overrideWithValue(AsyncValue.error(21, stackTrace: stackTrace)),
-      ]);
+  //     container.updateOverrides([
+  //       provider
+  //           .overrideWithValue(AsyncValue.error(21, stackTrace: stackTrace)),
+  //     ]);
+
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       throwsA(21),
+  //     );
+  //     expect(sub.read(), AsyncValue<int>.error(21, stackTrace: stackTrace));
+  //   });
 
-      await expectLater(
-        container.read(provider.future),
-        throwsA(21),
-      );
-      expect(sub.read(), AsyncValue<int>.error(21, stackTrace: stackTrace));
-    });
-
-    test('error immediately then different stacktrace', () async {
-      final stackTrace = StackTrace.current;
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider
-            .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
-      ]);
-
-      final future = container.read(provider.future);
-
-      await expectLater(future, throwsA(42));
-
-      final sub = container.listen(provider, (_, __) {});
-
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
-
-      final stack2 = StackTrace.current;
-
-      container.updateOverrides([
-        provider.overrideWithValue(AsyncValue.error(42, stackTrace: stack2)),
-      ]);
-
-      expect(
-        container.read(provider.future),
-        isNot(future),
-      );
-      await expectLater(
-        container.read(provider.future),
-        throwsA(42),
-      );
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stack2));
-    });
-
-    test('error immediately then data', () async {
-      final stackTrace = StackTrace.current;
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider
-            .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
-      ]);
-
-      await expectLater(
-        container.read(provider.future),
-        throwsA(42),
-      );
-
-      final sub = container.listen(provider, (_, __) {});
-
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
-
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
-
-      await expectLater(
-        container.read(provider.future),
-        completion(42),
-      );
-      expect(
-        sub.read(),
-        const AsyncValue<int>.data(42)
-            .copyWithPrevious(AsyncError(42, stackTrace: stackTrace)),
-      );
-    });
-
-    test('error immediately then loading', () async {
-      final stackTrace = StackTrace.current;
-      final provider = FutureProvider((_) async => 0);
-      final container = createContainer(overrides: [
-        provider
-            .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
-      ]);
-
-      final future = container.read(provider.future);
-      await expectLater(future, throwsA(42));
-
-      final sub = container.listen(provider, (_, __) {});
-
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
-
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.loading()),
-      ]);
-
-      expect(container.read(provider.future), isNot(future));
-      expect(
-        sub.read(),
-        const AsyncLoading<int>()
-            .copyWithPrevious(AsyncError<int>(42, stackTrace: stackTrace)),
-      );
-    });
-  });
+  //   test('error immediately then different stacktrace', () async {
+  //     final stackTrace = StackTrace.current;
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider
+  //           .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
+  //     ]);
+
+  //     final future = container.read(provider.future);
+
+  //     await expectLater(future, throwsA(42));
+
+  //     final sub = container.listen(provider, (_, __) {});
+
+  //     expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+
+  //     final stack2 = StackTrace.current;
+
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(AsyncValue.error(42, stackTrace: stack2)),
+  //     ]);
+
+  //     expect(
+  //       container.read(provider.future),
+  //       isNot(future),
+  //     );
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       throwsA(42),
+  //     );
+  //     expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stack2));
+  //   });
+
+  //   test('error immediately then data', () async {
+  //     final stackTrace = StackTrace.current;
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider
+  //           .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
+  //     ]);
+
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       throwsA(42),
+  //     );
+
+  //     final sub = container.listen(provider, (_, __) {});
+
+  //     expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(const AsyncValue.data(42)),
+  //     ]);
+
+  //     await expectLater(
+  //       container.read(provider.future),
+  //       completion(42),
+  //     );
+  //     expect(
+  //       sub.read(),
+  //       const AsyncValue<int>.data(42)
+  //           .copyWithPrevious(AsyncError(42, stackTrace: stackTrace)),
+  //     );
+  //   });
+
+  //   test('error immediately then loading', () async {
+  //     final stackTrace = StackTrace.current;
+  //     final provider = FutureProvider((_) async => 0);
+  //     final container = createContainer(overrides: [
+  //       provider
+  //           .overrideWithValue(AsyncValue.error(42, stackTrace: stackTrace)),
+  //     ]);
+
+  //     final future = container.read(provider.future);
+  //     await expectLater(future, throwsA(42));
+
+  //     final sub = container.listen(provider, (_, __) {});
+
+  //     expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+
+  //     container.updateOverrides([
+  //       provider.overrideWithValue(const AsyncValue.loading()),
+  //     ]);
+
+  //     expect(container.read(provider.future), isNot(future));
+  //     expect(
+  //       sub.read(),
+  //       const AsyncLoading<int>()
+  //           .copyWithPrevious(AsyncError<int>(42, stackTrace: stackTrace)),
+  //     );
+  //   });
+  // });
 }
diff --git a/packages/riverpod/test/providers/provider/auto_dispose_provider_family_test.dart b/packages/riverpod/test/providers/provider/auto_dispose_provider_family_test.dart
index 00ba69a91b..2a88639811 100644
--- a/packages/riverpod/test/providers/provider/auto_dispose_provider_family_test.dart
+++ b/packages/riverpod/test/providers/provider/auto_dispose_provider_family_test.dart
@@ -46,23 +46,6 @@ void main() {
       expect(provider(0).argument, 0);
     });
 
-    test(
-        'on async provider, specifies `from` and `argument` for related providers',
-        () {
-      final provider = Provider.autoDispose.family<AsyncValue<int>, int>(
-        (ref, _) => const AsyncValue.data(42),
-      );
-
-      expect(provider(0).from, provider);
-      expect(provider(0).argument, 0);
-
-      expect(provider(0).future.from, provider);
-      expect(provider(0).future.argument, 0);
-
-      expect(provider(0).stream.from, provider);
-      expect(provider(0).stream.argument, 0);
-    });
-
     group('scoping an override overrides all the associated subproviders', () {
       test('when passing the provider itself', () {
         final provider = Provider.autoDispose.family<int, int>((ref, _) => 0);
diff --git a/packages/riverpod/test/providers/provider/auto_dispose_provider_test.dart b/packages/riverpod/test/providers/provider/auto_dispose_provider_test.dart
index cc098396fc..8e3be01df7 100644
--- a/packages/riverpod/test/providers/provider/auto_dispose_provider_test.dart
+++ b/packages/riverpod/test/providers/provider/auto_dispose_provider_test.dart
@@ -6,26 +6,6 @@ import '../../utils.dart';
 
 void main() {
   group('Provider.autoDispose', () {
-    test('can benefit from .future extension if returning an AsyncValue',
-        () async {
-      final container = createContainer();
-      final provider = Provider.autoDispose((ref) => const AsyncValue.data(42));
-
-      container.listen(provider, (previous, next) {});
-
-      await expectLater(container.read(provider.future), completion(42));
-    });
-
-    test('can benefit from .stream extension if returning an AsyncValue',
-        () async {
-      final container = createContainer();
-      final provider = Provider.autoDispose((ref) => const AsyncValue.data(42));
-
-      container.listen(provider, (previous, next) {});
-
-      await expectLater(container.read(provider.stream), emits(42));
-    });
-
     group('ref.state', () {
       test('can read and change current value', () {
         final container = createContainer();
@@ -178,8 +158,8 @@ void main() {
     });
 
     test('can be overridden by anything', () {
-      final provider = Provider.autoDispose((_) => 42);
-      final AutoDisposeProviderBase<int> override = Provider.autoDispose((_) {
+      final provider = Provider.autoDispose<num>((_) => 42);
+      final override = Provider.autoDispose<int>((_) {
         return 21;
       });
       final container = createContainer(overrides: [
diff --git a/packages/riverpod/test/providers/provider/provider_family_test.dart b/packages/riverpod/test/providers/provider/provider_family_test.dart
index 0c415fafd5..628943d4f6 100644
--- a/packages/riverpod/test/providers/provider/provider_family_test.dart
+++ b/packages/riverpod/test/providers/provider/provider_family_test.dart
@@ -12,23 +12,6 @@ void main() {
       expect(provider(0).argument, 0);
     });
 
-    test(
-        'on async provider, specifies `from` and `argument` for related providers',
-        () {
-      final provider = Provider.family<AsyncValue<int>, int>(
-        (ref, _) => const AsyncValue.data(42),
-      );
-
-      expect(provider(0).from, provider);
-      expect(provider(0).argument, 0);
-
-      expect(provider(0).future.from, provider);
-      expect(provider(0).future.argument, 0);
-
-      expect(provider(0).stream.from, provider);
-      expect(provider(0).stream.argument, 0);
-    });
-
     group('scoping an override overrides all the associated subproviders', () {
       test('when passing the provider itself', () {
         final provider = Provider.family<int, int>((ref, _) => 0);
diff --git a/packages/riverpod/test/providers/provider/provider_test.dart b/packages/riverpod/test/providers/provider/provider_test.dart
index 95539041a9..0b616033e8 100644
--- a/packages/riverpod/test/providers/provider/provider_test.dart
+++ b/packages/riverpod/test/providers/provider/provider_test.dart
@@ -6,22 +6,6 @@ import '../../utils.dart';
 
 void main() {
   group('Provider', () {
-    test('can benefit from .future extension if returning an AsyncValue',
-        () async {
-      final container = createContainer();
-      final provider = Provider((ref) => const AsyncValue.data(42));
-
-      await expectLater(container.read(provider.future), completion(42));
-    });
-
-    test('can benefit from .stream extension if returning an AsyncValue',
-        () async {
-      final container = createContainer();
-      final provider = Provider((ref) => const AsyncValue.data(42));
-
-      await expectLater(container.read(provider.stream), emits(42));
-    });
-
     test('can be refreshed', () async {
       var result = 0;
       final container = createContainer();
@@ -192,18 +176,6 @@ void main() {
     });
 
     group('override', () {
-      test('Provider can be overridden by anything', () {
-        final provider = Provider((_) => 42);
-        final AlwaysAliveProviderBase<int> override = Provider((_) {
-          return 21;
-        });
-        final container = createContainer(overrides: [
-          provider.overrideWithProvider(override),
-        ]);
-
-        expect(container.read(provider), 21);
-      });
-
       test('does not notify listeners if updated with the same value', () {
         final provider = Provider((ref) => 0);
         final container = createContainer(overrides: [
diff --git a/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_family_test.dart b/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_family_test.dart
index f723e2d273..0087e0ce93 100644
--- a/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_family_test.dart
+++ b/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_family_test.dart
@@ -48,9 +48,6 @@ void main() {
 
       expect(provider(0).from, provider);
       expect(provider(0).argument, 0);
-
-      expect(provider(0).notifier.from, provider);
-      expect(provider(0).notifier.argument, 0);
     });
 
     test('can be auto-scoped', () async {
@@ -89,8 +86,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
         expect(root.getAllProviderElementsInOrder(), isEmpty);
@@ -117,8 +112,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
       });
diff --git a/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_state_notifier_provider_test.dart b/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_state_notifier_provider_test.dart
index 407eb36bfb..8b1d7d0ce6 100644
--- a/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_state_notifier_provider_test.dart
+++ b/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_state_notifier_provider_test.dart
@@ -90,88 +90,82 @@ void main() {
         unorderedEquals(<Object?>[
           isA<ProviderElementBase>()
               .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier),
         ]),
       );
     });
 
-    test('when using provider.overrideWithValue', () async {
-      final controller = StateController(0);
-      final provider =
-          StateNotifierProvider.autoDispose<StateController<int>, int>(
-              (ref) => controller);
-      final root = createContainer();
-      final controllerOverride = StateController(42);
-      final container = createContainer(parent: root, overrides: [
-        provider.overrideWithValue(controllerOverride),
-      ]);
-
-      expect(container.read(provider.notifier), controllerOverride);
-      expect(container.read(provider), 42);
-      expect(root.getAllProviderElements(), isEmpty);
-      expect(
-        container.getAllProviderElements(),
-        unorderedEquals(<Object?>[
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier),
-        ]),
-      );
-    });
+    // test('when using provider.overrideWithValue', () async {
+    //   final controller = StateController(0);
+    //   final provider =
+    //       StateNotifierProvider.autoDispose<StateController<int>, int>(
+    //           (ref) => controller);
+    //   final root = createContainer();
+    //   final controllerOverride = StateController(42);
+    //   final container = createContainer(parent: root, overrides: [
+    //     provider.overrideWithValue(controllerOverride),
+    //   ]);
+
+    //   expect(container.read(provider.notifier), controllerOverride);
+    //   expect(container.read(provider), 42);
+    //   expect(root.getAllProviderElements(), isEmpty);
+    //   expect(
+    //     container.getAllProviderElements(),
+    //     unorderedEquals(<Object?>[
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider),
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider.notifier),
+    //     ]),
+    //   );
+    // });
   });
 
-  test('overriding the provider overrides provider.state too', () {
-    final provider = StateNotifierProvider.autoDispose<TestNotifier, int>((_) {
-      return TestNotifier();
-    });
-    final notifier = TestNotifier(42);
-    final container = createContainer(
-      overrides: [
-        provider.overrideWithValue(TestNotifier(10)),
-      ],
-    );
-    addTearDown(container.dispose);
-    final stateListener = Listener<int>();
-    final notifierListener = Listener<TestNotifier>();
-
-    // does not crash
-    container.updateOverrides([
-      provider.overrideWithValue(notifier),
-    ]);
-
-    container.listen(
-      provider.notifier,
-      notifierListener,
-      fireImmediately: true,
-    );
-    verify(notifierListener(null, notifier)).called(1);
-    verifyNoMoreInteractions(notifierListener);
-
-    container.listen(provider, stateListener, fireImmediately: true);
-    verify(stateListener(null, 42)).called(1);
-    verifyNoMoreInteractions(stateListener);
-
-    notifier.increment();
-
-    verify(stateListener(42, 43)).called(1);
-    verifyNoMoreInteractions(notifierListener);
-    verifyNoMoreInteractions(stateListener);
-  });
+  // test('overriding the provider overrides provider.state too', () {
+  //   final provider = StateNotifierProvider.autoDispose<TestNotifier, int>((_) {
+  //     return TestNotifier();
+  //   });
+  //   final notifier = TestNotifier(42);
+  //   final container = createContainer(
+  //     overrides: [
+  //       provider.overrideWithValue(TestNotifier(10)),
+  //     ],
+  //   );
+  //   addTearDown(container.dispose);
+  //   final stateListener = Listener<int>();
+  //   final notifierListener = Listener<TestNotifier>();
+
+  //   // does not crash
+  //   container.updateOverrides([
+  //     provider.overrideWithValue(notifier),
+  //   ]);
+
+  //   container.listen(
+  //     provider.notifier,
+  //     notifierListener,
+  //     fireImmediately: true,
+  //   );
+  //   verify(notifierListener(null, notifier)).called(1);
+  //   verifyNoMoreInteractions(notifierListener);
+
+  //   container.listen(provider, stateListener, fireImmediately: true);
+  //   verify(stateListener(null, 42)).called(1);
+  //   verifyNoMoreInteractions(stateListener);
+
+  //   notifier.increment();
+
+  //   verify(stateListener(42, 43)).called(1);
+  //   verifyNoMoreInteractions(notifierListener);
+  //   verifyNoMoreInteractions(stateListener);
+  // });
 
   test('can specify name', () {
     final provider = StateNotifierProvider.autoDispose(
       (_) => TestNotifier(),
       name: 'example',
     );
-
-    expect(provider.notifier.name, 'example.notifier');
-    expect(provider.name, 'example');
-
     final provider2 = StateNotifierProvider.autoDispose((_) => TestNotifier());
 
-    expect(provider2.notifier.name, isNull);
+    expect(provider.name, 'example');
     expect(provider2.name, isNull);
   });
 
diff --git a/packages/riverpod/test/providers/state_notifier_provider/family_test.dart b/packages/riverpod/test/providers/state_notifier_provider/family_test.dart
index 7d70042cd9..cbeb24aa7a 100644
--- a/packages/riverpod/test/providers/state_notifier_provider/family_test.dart
+++ b/packages/riverpod/test/providers/state_notifier_provider/family_test.dart
@@ -14,9 +14,6 @@ void main() {
 
       expect(provider(0).from, provider);
       expect(provider(0).argument, 0);
-
-      expect(provider(0).notifier.from, provider);
-      expect(provider(0).notifier.argument, 0);
     });
 
     test('can be auto-scoped', () async {
@@ -55,8 +52,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
         expect(root.getAllProviderElementsInOrder(), isEmpty);
@@ -83,8 +78,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
       });
@@ -131,8 +124,6 @@ void main() {
         expect(
           container.getAllProviderElementsInOrder(),
           [
-            isA<ProviderElementBase>()
-                .having((e) => e.provider, 'provider', family('0').notifier),
             isA<ProviderElementBase>()
                 .having((e) => e.provider, 'provider', family('0')),
           ],
diff --git a/packages/riverpod/test/providers/state_notifier_provider/state_notifier_provider_test.dart b/packages/riverpod/test/providers/state_notifier_provider/state_notifier_provider_test.dart
index 89ef009c7b..bb6de09a50 100644
--- a/packages/riverpod/test/providers/state_notifier_provider/state_notifier_provider_test.dart
+++ b/packages/riverpod/test/providers/state_notifier_provider/state_notifier_provider_test.dart
@@ -5,6 +5,23 @@ import 'package:test/test.dart';
 import '../../utils.dart';
 
 void main() {
+  test('ref.listenSelf listens to state changes', () {
+    final listener = Listener<int>();
+    final container = createContainer();
+    final provider = StateNotifierProvider<StateController<int>, int>((ref) {
+      ref.listenSelf(listener);
+      return StateController(0);
+    });
+
+    final notifier = container.read(provider.notifier);
+
+    verifyOnly(listener, listener(null, 0));
+
+    notifier.state++;
+
+    verifyOnly(listener, listener(0, 1));
+  });
+
   test('can read and set current StateNotifier', () async {
     final container = createContainer();
     final listener = Listener<int>();
@@ -86,35 +103,33 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.notifier),
           ]),
         );
       });
 
-      test('when using provider.overrideWithValue', () async {
-        final controller = StateController(0);
-        final provider = StateNotifierProvider<StateController<int>, int>(
-            (ref) => controller);
-        final root = createContainer();
-        final controllerOverride = StateController(42);
-        final container = createContainer(parent: root, overrides: [
-          provider.overrideWithValue(controllerOverride),
-        ]);
-
-        expect(container.read(provider.notifier), controllerOverride);
-        expect(container.read(provider), 42);
-        expect(root.getAllProviderElements(), isEmpty);
-        expect(
-          container.getAllProviderElements(),
-          unorderedEquals(<Object?>[
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.notifier),
-          ]),
-        );
-      });
+      // test('when using provider.overrideWithValue', () async {
+      //   final controller = StateController(0);
+      //   final provider = StateNotifierProvider<StateController<int>, int>(
+      //       (ref) => controller);
+      //   final root = createContainer();
+      //   final controllerOverride = StateController(42);
+      //   final container = createContainer(parent: root, overrides: [
+      //     provider.overrideWithValue(controllerOverride),
+      //   ]);
+
+      //   expect(container.read(provider.notifier), controllerOverride);
+      //   expect(container.read(provider), 42);
+      //   expect(root.getAllProviderElements(), isEmpty);
+      //   expect(
+      //     container.getAllProviderElements(),
+      //     unorderedEquals(<Object?>[
+      //       isA<ProviderElementBase>()
+      //           .having((e) => e.origin, 'origin', provider),
+      //       isA<ProviderElementBase>()
+      //           .having((e) => e.origin, 'origin', provider.notifier),
+      //     ]),
+      //   );
+      // });
 
       test('when using provider.overrideWithProvider', () async {
         final controller = StateController(0);
@@ -138,50 +153,44 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.notifier),
           ]),
         );
       });
     });
   });
 
-  test('overriding the provider overrides provider.state too', () {
-    final notifier = TestNotifier(42);
-    final provider =
-        StateNotifierProvider<TestNotifier, int>((_) => TestNotifier());
-    final container = createContainer(
-      overrides: [
-        provider.overrideWithValue(TestNotifier(10)),
-      ],
-    );
-    addTearDown(container.dispose);
+  // test('overriding the provider overrides provider.state too', () {
+  //   final notifier = TestNotifier(42);
+  //   final provider =
+  //       StateNotifierProvider<TestNotifier, int>((_) => TestNotifier());
+  //   final container = createContainer(
+  //     overrides: [
+  //       provider.overrideWithValue(TestNotifier(10)),
+  //     ],
+  //   );
+  //   addTearDown(container.dispose);
 
-    // does not crash
-    container.updateOverrides([
-      provider.overrideWithValue(notifier),
-    ]);
+  //   // does not crash
+  //   container.updateOverrides([
+  //     provider.overrideWithValue(notifier),
+  //   ]);
 
-    expect(container.read(provider.notifier), notifier);
-    expect(container.read(provider), 42);
+  //   expect(container.read(provider.notifier), notifier);
+  //   expect(container.read(provider), 42);
 
-    notifier.increment();
+  //   notifier.increment();
 
-    expect(container.read(provider), 43);
-  });
+  //   expect(container.read(provider), 43);
+  // });
 
   test('can specify name', () {
     final provider = StateNotifierProvider<TestNotifier, int>((_) {
       return TestNotifier();
     }, name: 'example');
-
-    expect(provider.notifier.name, 'example.notifier');
-    expect(provider.name, 'example');
-
     final provider2 =
         StateNotifierProvider<TestNotifier, int>((_) => TestNotifier());
 
-    expect(provider2.notifier.name, isNull);
+    expect(provider.name, 'example');
     expect(provider2.name, isNull);
   });
 
@@ -284,50 +293,50 @@ void main() {
     expect(callCount, 1);
   });
 
-  test(
-      'overrideWithValue listens to the notifier, support notifier change, and does not dispose of the notifier',
-      () async {
-    final provider = StateNotifierProvider<TestNotifier, int>((_) {
-      return TestNotifier();
-    });
-    final notifier = TestNotifier(42);
-    final notifier2 = TestNotifier(21);
-    final container = createContainer(overrides: [
-      provider.overrideWithValue(notifier),
-    ]);
-    addTearDown(container.dispose);
-    final listener = Listener<int>();
+  // test(
+  //     'overrideWithValue listens to the notifier, support notifier change, and does not dispose of the notifier',
+  //     () async {
+  //   final provider = StateNotifierProvider<TestNotifier, int>((_) {
+  //     return TestNotifier();
+  //   });
+  //   final notifier = TestNotifier(42);
+  //   final notifier2 = TestNotifier(21);
+  //   final container = createContainer(overrides: [
+  //     provider.overrideWithValue(notifier),
+  //   ]);
+  //   addTearDown(container.dispose);
+  //   final listener = Listener<int>();
 
-    container.listen<int>(provider, listener, fireImmediately: true);
+  //   container.listen<int>(provider, listener, fireImmediately: true);
 
-    verifyOnly(listener, listener(null, 42));
-    expect(container.read(provider.notifier), notifier);
-    expect(notifier.hasListeners, true);
+  //   verifyOnly(listener, listener(null, 42));
+  //   expect(container.read(provider.notifier), notifier);
+  //   expect(notifier.hasListeners, true);
 
-    notifier.increment();
+  //   notifier.increment();
 
-    await container.pump();
+  //   await container.pump();
 
-    verifyOnly(listener, listener(42, 43));
+  //   verifyOnly(listener, listener(42, 43));
 
-    container.updateOverrides([
-      provider.overrideWithValue(notifier2),
-    ]);
+  //   container.updateOverrides([
+  //     provider.overrideWithValue(notifier2),
+  //   ]);
 
-    await container.pump();
+  //   await container.pump();
 
-    verifyOnly(listener, listener(43, 21));
+  //   verifyOnly(listener, listener(43, 21));
 
-    expect(notifier.hasListeners, false);
-    expect(notifier.mounted, true);
-    expect(container.read(provider.notifier), notifier2);
+  //   expect(notifier.hasListeners, false);
+  //   expect(notifier.mounted, true);
+  //   expect(container.read(provider.notifier), notifier2);
 
-    notifier2.increment();
+  //   notifier2.increment();
 
-    await container.pump();
+  //   await container.pump();
 
-    verifyOnly(listener, listener(21, 22));
-  });
+  //   verifyOnly(listener, listener(21, 22));
+  // });
 
   test('overrideWithProvider preserves the state across update', () async {
     final provider = StateNotifierProvider<TestNotifier, int>((_) {
diff --git a/packages/riverpod/test/providers/state_provider/state_provider_auto_dispose_test.dart b/packages/riverpod/test/providers/state_provider/state_provider_auto_dispose_test.dart
index d620a639aa..ab62fe1254 100644
--- a/packages/riverpod/test/providers/state_provider/state_provider_auto_dispose_test.dart
+++ b/packages/riverpod/test/providers/state_provider/state_provider_auto_dispose_test.dart
@@ -6,24 +6,6 @@ import '../../utils.dart';
 
 void main() {
   test('supports .name', () {
-    expect(
-      StateProvider.autoDispose((ref) => 0).state.name,
-      null,
-    );
-    expect(
-      StateProvider.autoDispose((ref) => 0, name: 'foo').state.name,
-      'foo.state',
-    );
-
-    expect(
-      StateProvider.autoDispose((ref) => 0).notifier.name,
-      null,
-    );
-    expect(
-      StateProvider.autoDispose((ref) => 0, name: 'foo').notifier.name,
-      'foo.notifier',
-    );
-
     expect(
       StateProvider.autoDispose((ref) => 0).name,
       null,
@@ -119,25 +101,6 @@ void main() {
     });
   });
 
-  test('is compatible with ProviderObserver', () {
-    // regression test for https://github.com/rrousselGit/river_pod/issues/623
-
-    final observer = ObserverMock();
-    final container = createContainer(observers: [observer]);
-    final provider = StateProvider.autoDispose<int>((_) => 0);
-
-    final notifier = container.read(provider.state);
-
-    clearInteractions(observer);
-
-    notifier.state++;
-
-    verifyOnly(
-      observer,
-      observer.didUpdateProvider(provider.state, notifier, notifier, container),
-    );
-  });
-
   test('can refresh .notifier', () async {
     var initialValue = 1;
     final provider = StateProvider.autoDispose<int>((ref) => initialValue);
@@ -201,39 +164,35 @@ void main() {
       expect(
         container.getAllProviderElements(),
         unorderedEquals(<Object?>[
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.state),
           isA<ProviderElementBase>()
               .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier),
         ]),
       );
     });
 
-    test('when using provider.overrideWithValue', () async {
-      final provider = StateProvider.autoDispose<int>((ref) => 0);
-      final root = createContainer();
-      final container = createContainer(parent: root, overrides: [
-        provider.overrideWithValue(StateController(42)),
-      ]);
-
-      expect(container.read(provider.notifier).state, 42);
-      expect(container.read(provider.state).state, 42);
-      expect(container.read(provider), 42);
-      expect(root.getAllProviderElements(), isEmpty);
-      expect(
-        container.getAllProviderElements(),
-        unorderedEquals(<Object?>[
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.state),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier),
-        ]),
-      );
-    });
+    // test('when using provider.overrideWithValue', () async {
+    //   final provider = StateProvider.autoDispose<int>((ref) => 0);
+    //   final root = createContainer();
+    //   final container = createContainer(parent: root, overrides: [
+    //     provider.overrideWithValue(StateController(42)),
+    //   ]);
+
+    //   expect(container.read(provider.notifier).state, 42);
+    //   expect(container.read(provider.state).state, 42);
+    //   expect(container.read(provider), 42);
+    //   expect(root.getAllProviderElements(), isEmpty);
+    //   expect(
+    //     container.getAllProviderElements(),
+    //     unorderedEquals(<Object?>[
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider),
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider.state),
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider.notifier),
+    //     ]),
+    //   );
+    // });
 
     test('when using provider.overrideWithProvider', () async {
       final provider = StateProvider.autoDispose<int>((ref) => 0, name: 'true');
@@ -252,10 +211,6 @@ void main() {
         unorderedEquals(<Object?>[
           isA<ProviderElementBase>()
               .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.state),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier),
         ]),
       );
       expect(root.getAllProviderElements(), isEmpty);
@@ -263,24 +218,24 @@ void main() {
   });
 
   group('overrideWithProvider', () {
-    test('listens to state changes', () {
-      final override = StateController(42);
-      final provider = StateProvider.autoDispose((ref) => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(override),
-      ]);
-      addTearDown(container.dispose);
-      final container2 = ProviderContainer(overrides: [
-        provider.overrideWithProvider(
-          StateProvider.autoDispose((ref) => 42),
-        ),
-      ]);
-      addTearDown(container.dispose);
-
-      expect(container.read(provider), 42);
-      expect(container.read(provider.notifier), override);
-      expect(container2.read(provider.state).state, 42);
-    });
+    // test('listens to state changes', () {
+    //   final override = StateController(42);
+    //   final provider = StateProvider.autoDispose((ref) => 0);
+    //   final container = createContainer(overrides: [
+    //     provider.overrideWithValue(override),
+    //   ]);
+    //   addTearDown(container.dispose);
+    //   final container2 = ProviderContainer(overrides: [
+    //     provider.overrideWithProvider(
+    //       StateProvider.autoDispose((ref) => 42),
+    //     ),
+    //   ]);
+    //   addTearDown(container.dispose);
+
+    //   expect(container.read(provider), 42);
+    //   expect(container.read(provider.notifier), override);
+    //   expect(container2.read(provider.state).state, 42);
+    // });
 
     test(
       'properly disposes of the StateController when the provider is disposed',
diff --git a/packages/riverpod/test/providers/state_provider/state_provider_family_auto_dispose_test.dart b/packages/riverpod/test/providers/state_provider/state_provider_family_auto_dispose_test.dart
index 496b9223c0..c79f07dbee 100644
--- a/packages/riverpod/test/providers/state_provider/state_provider_family_auto_dispose_test.dart
+++ b/packages/riverpod/test/providers/state_provider/state_provider_family_auto_dispose_test.dart
@@ -7,33 +7,6 @@ import '../../utils.dart';
 
 void main() {
   test('supports .name', () {
-    expect(
-      StateProvider.autoDispose.family<int, int>((ref, id) => 0)(0).state.name,
-      null,
-    );
-    expect(
-      StateProvider.autoDispose
-          .family<int, int>((ref, id) => 0, name: 'foo')(0)
-          .state
-          .name,
-      'foo.state',
-    );
-
-    expect(
-      StateProvider.autoDispose
-          .family<int, int>((ref, id) => 0)(0)
-          .notifier
-          .name,
-      null,
-    );
-    expect(
-      StateProvider.autoDispose
-          .family<int, int>((ref, id) => 0, name: 'foo')(0)
-          .notifier
-          .name,
-      'foo.notifier',
-    );
-
     expect(
       StateProvider.autoDispose.family<int, int>((ref, id) => 0)(0).name,
       null,
@@ -87,18 +60,6 @@ void main() {
 
       expect(provider(0).from, provider);
       expect(provider(0).argument, 0);
-
-      expect(provider(0).state.from, provider);
-      expect(provider(0).state.argument, 0);
-
-      expect(provider(0).notifier.from, provider);
-      expect(provider(0).notifier.argument, 0);
-
-      expect(provider(0).future.from, provider);
-      expect(provider(0).future.argument, 0);
-
-      expect(provider(0).stream.from, provider);
-      expect(provider(0).stream.argument, 0);
     });
 
     group('scoping an override overrides all the associated subproviders', () {
@@ -114,9 +75,7 @@ void main() {
           container.getAllProviderElementsInOrder(),
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).state),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
+                .having((e) => e.origin, 'origin', provider(0)),
           ]),
         );
         expect(root.getAllProviderElementsInOrder(), isEmpty);
@@ -139,9 +98,7 @@ void main() {
           container.getAllProviderElementsInOrder(),
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).state),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
+                .having((e) => e.origin, 'origin', provider(0)),
           ]),
         );
       });
diff --git a/packages/riverpod/test/providers/state_provider/state_provider_family_test.dart b/packages/riverpod/test/providers/state_provider/state_provider_family_test.dart
index 4583b4cc9c..d63dd2b538 100644
--- a/packages/riverpod/test/providers/state_provider/state_provider_family_test.dart
+++ b/packages/riverpod/test/providers/state_provider/state_provider_family_test.dart
@@ -5,26 +5,6 @@ import '../../utils.dart';
 
 void main() {
   test('supports .name', () {
-    expect(
-      StateProvider.family<int, int>((ref, id) => 0)(0).state.name,
-      null,
-    );
-    expect(
-      StateProvider.family<int, int>((ref, id) => 0, name: 'foo')(0).state.name,
-      'foo.state',
-    );
-
-    expect(
-      StateProvider.family<int, int>((ref, id) => 0)(0).notifier.name,
-      null,
-    );
-    expect(
-      StateProvider.family<int, int>((ref, id) => 0, name: 'foo')(0)
-          .notifier
-          .name,
-      'foo.notifier',
-    );
-
     expect(
       StateProvider.family<int, int>((ref, id) => 0)(0).name,
       null,
@@ -43,18 +23,6 @@ void main() {
 
       expect(provider(0).from, provider);
       expect(provider(0).argument, 0);
-
-      expect(provider(0).state.from, provider);
-      expect(provider(0).state.argument, 0);
-
-      expect(provider(0).notifier.from, provider);
-      expect(provider(0).notifier.argument, 0);
-
-      expect(provider(0).future.from, provider);
-      expect(provider(0).future.argument, 0);
-
-      expect(provider(0).stream.from, provider);
-      expect(provider(0).stream.argument, 0);
     });
 
     group('scoping an override overrides all the associated subproviders', () {
@@ -71,10 +39,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).state),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
         expect(root.getAllProviderElementsInOrder(), isEmpty);
@@ -98,10 +62,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).state),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).notifier),
           ]),
         );
       });
diff --git a/packages/riverpod/test/providers/state_provider/state_provider_test.dart b/packages/riverpod/test/providers/state_provider/state_provider_test.dart
index 7e7d88602b..f0b21622c9 100644
--- a/packages/riverpod/test/providers/state_provider/state_provider_test.dart
+++ b/packages/riverpod/test/providers/state_provider/state_provider_test.dart
@@ -5,25 +5,24 @@ import 'package:test/test.dart';
 import '../../utils.dart';
 
 void main() {
-  test('supports .name', () {
-    expect(
-      StateProvider((ref) => 0).state.name,
-      null,
-    );
-    expect(
-      StateProvider((ref) => 0, name: 'foo').state.name,
-      'foo.state',
-    );
+  test('ref.listenSelf listens to state changes', () {
+    final listener = Listener<int>();
+    final container = createContainer();
+    final provider = StateProvider<int>((ref) {
+      ref.listenSelf(listener);
+      return 0;
+    });
 
-    expect(
-      StateProvider((ref) => 0).notifier.name,
-      null,
-    );
-    expect(
-      StateProvider((ref) => 0, name: 'foo').notifier.name,
-      'foo.notifier',
-    );
+    final notifier = container.read(provider.notifier);
 
+    verifyOnly(listener, listener(null, 0));
+
+    notifier.state++;
+
+    verifyOnly(listener, listener(0, 1));
+  });
+
+  test('supports .name', () {
     expect(
       StateProvider((ref) => 0).name,
       null,
@@ -73,25 +72,6 @@ void main() {
     expect(root.getAllProviderElements(), isEmpty);
   });
 
-  test('is compatible with ProviderObserver', () {
-    // regression test for https://github.com/rrousselGit/river_pod/issues/623
-
-    final observer = ObserverMock();
-    final container = createContainer(observers: [observer]);
-    final provider = StateProvider<int>((ref) => 0);
-
-    final notifier = container.read(provider.state);
-
-    clearInteractions(observer);
-
-    notifier.state++;
-
-    verifyOnly(
-      observer,
-      observer.didUpdateProvider(provider.state, notifier, notifier, container),
-    );
-  });
-
   group('ref.state', () {
     test('can read and change current value', () {
       final container = createContainer();
@@ -218,33 +198,31 @@ void main() {
         container.getAllProviderElements(),
         unorderedEquals(<Object?>[
           isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.state),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier),
+              .having((e) => e.origin, 'origin', provider),
         ]),
       );
     });
 
-    test('when using provider.overrideWithValue', () async {
-      final provider = StateProvider<int>((ref) => 0);
-      final root = createContainer();
-      final container = createContainer(parent: root, overrides: [
-        provider.overrideWithValue(StateController(42)),
-      ]);
-
-      expect(container.read(provider.notifier).state, 42);
-      expect(container.read(provider.state).state, 42);
-      expect(root.getAllProviderElements(), isEmpty);
-      expect(
-        container.getAllProviderElements(),
-        unorderedEquals(<Object?>[
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.state),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier),
-        ]),
-      );
-    });
+    // test('when using provider.overrideWithValue', () async {
+    //   final provider = StateProvider<int>((ref) => 0);
+    //   final root = createContainer();
+    //   final container = createContainer(parent: root, overrides: [
+    //     provider.overrideWithValue(StateController(42)),
+    //   ]);
+
+    //   expect(container.read(provider.notifier).state, 42);
+    //   expect(container.read(provider.state).state, 42);
+    //   expect(root.getAllProviderElements(), isEmpty);
+    //   expect(
+    //     container.getAllProviderElements(),
+    //     unorderedEquals(<Object?>[
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider.state),
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider.notifier),
+    //     ]),
+    //   );
+    // });
 
     test('when using provider.overrideWithProvider', () async {
       final provider = StateProvider<int>((ref) => 0);
@@ -262,56 +240,54 @@ void main() {
         container.getAllProviderElements(),
         unorderedEquals(<Object?>[
           isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.state),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.notifier),
+              .having((e) => e.origin, 'origin', provider),
         ]),
       );
     });
   });
 
-  test(
-    'overrideWithValue listens to the new StateController and support controller changes',
-    () {
-      final provider = StateProvider((ref) => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(StateController(42)),
-      ]);
-      final listener = Listener<int>();
+  // test(
+  //   'overrideWithValue listens to the new StateController and support controller changes',
+  //   () {
+  //     final provider = StateProvider((ref) => 0);
+  //     final container = createContainer(overrides: [
+  //       provider.overrideWithValue(StateController(42)),
+  //     ]);
+  //     final listener = Listener<int>();
 
-      container.listen<StateController<int>>(
-        provider.state,
-        (prev, controller) => listener(prev?.state, controller.state),
-        fireImmediately: true,
-      );
+  //     container.listen<StateController<int>>(
+  //       provider.state,
+  //       (prev, controller) => listener(prev?.state, controller.state),
+  //       fireImmediately: true,
+  //     );
 
-      verifyOnly(listener, listener(null, 42));
+  //     verifyOnly(listener, listener(null, 42));
 
-      container.read(provider.state).state++;
+  //     container.read(provider.state).state++;
 
-      verifyOnly(listener, listener(43, 43));
-    },
-  );
+  //     verifyOnly(listener, listener(43, 43));
+  //   },
+  // );
 
   group('overrideWithProvider', () {
-    test('listens to state changes', () {
-      final override = StateController(21);
-      final provider = StateProvider((ref) => 0);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(override),
-      ]);
-      addTearDown(container.dispose);
-      final container2 = ProviderContainer(overrides: [
-        provider.overrideWithProvider(
-          StateProvider((ref) => 42),
-        ),
-      ]);
-      addTearDown(container.dispose);
-
-      expect(container.read(provider.notifier), override);
-      expect(container.read(provider), 21);
-      expect(container2.read(provider.state).state, 42);
-    });
+    // test('listens to state changes', () {
+    //   final override = StateController(21);
+    //   final provider = StateProvider((ref) => 0);
+    //   final container = createContainer(overrides: [
+    //     provider.overrideWithValue(override),
+    //   ]);
+    //   addTearDown(container.dispose);
+    //   final container2 = ProviderContainer(overrides: [
+    //     provider.overrideWithProvider(
+    //       StateProvider((ref) => 42),
+    //     ),
+    //   ]);
+    //   addTearDown(container.dispose);
+
+    //   expect(container.read(provider.notifier), override);
+    //   expect(container.read(provider), 21);
+    //   expect(container2.read(provider.state).state, 42);
+    // });
 
     test(
       'properly disposes of the StateController when the provider is disposed',
diff --git a/packages/riverpod/test/providers/stream_provider/auto_dispose_family_stream_provider_test.dart b/packages/riverpod/test/providers/stream_provider/auto_dispose_family_stream_provider_test.dart
index a272e69ecb..76fef77490 100644
--- a/packages/riverpod/test/providers/stream_provider/auto_dispose_family_stream_provider_test.dart
+++ b/packages/riverpod/test/providers/stream_provider/auto_dispose_family_stream_provider_test.dart
@@ -49,17 +49,6 @@ void main() {
 
       expect(provider(0).from, provider);
       expect(provider(0).argument, 0);
-
-      expect(provider(0).future.from, provider);
-      expect(provider(0).future.argument, 0);
-
-      expect(provider(0).stream.from, provider);
-      expect(provider(0).stream.argument, 0);
-
-      // ignore: deprecated_member_use_from_same_package
-      expect(provider(0).last.from, provider);
-      // ignore: deprecated_member_use_from_same_package
-      expect(provider(0).last.argument, 0);
     });
 
     group('scoping an override overrides all the associated subproviders', () {
@@ -78,10 +67,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).future),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).stream),
           ]),
         );
       });
diff --git a/packages/riverpod/test/providers/stream_provider/auto_dispose_stream_provider_test.dart b/packages/riverpod/test/providers/stream_provider/auto_dispose_stream_provider_test.dart
index fc89d4e374..0975861f6b 100644
--- a/packages/riverpod/test/providers/stream_provider/auto_dispose_stream_provider_test.dart
+++ b/packages/riverpod/test/providers/stream_provider/auto_dispose_stream_provider_test.dart
@@ -221,44 +221,40 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.future),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.stream),
           ]),
         );
       });
 
-      test('when using provider.overrideWithValue', () async {
-        final provider = StreamProvider.autoDispose((ref) => Stream.value(0));
-        final root = createContainer();
-        final container = createContainer(parent: root, overrides: [
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
-
-        expect(await container.read(provider.stream).first, 42);
-        expect(await container.read(provider.future), 42);
-        expect(container.read(provider), const AsyncValue.data(42));
-        expect(root.getAllProviderElements(), isEmpty);
-        expect(
-          container.getAllProviderElements(),
-          unorderedEquals(<Object?>[
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.future),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.stream),
-          ]),
-        );
-      });
+      // test('when using provider.overrideWithValue', () async {
+      //   final provider = StreamProvider.autoDispose((ref) => Stream.value(0));
+      //   final root = createContainer();
+      //   final container = createContainer(parent: root, overrides: [
+      //     provider.overrideWithValue(const AsyncValue.data(42)),
+      //   ]);
+
+      //   expect(await container.read(provider.stream).first, 42);
+      //   expect(await container.read(provider.future), 42);
+      //   expect(container.read(provider), const AsyncValue.data(42));
+      //   expect(root.getAllProviderElements(), isEmpty);
+      //   expect(
+      //     container.getAllProviderElements(),
+      //     unorderedEquals(<Object?>[
+      //       isA<ProviderElementBase>()
+      //           .having((e) => e.origin, 'origin', provider),
+      //       isA<ProviderElementBase>()
+      //           .having((e) => e.origin, 'origin', provider.future),
+      //       isA<ProviderElementBase>()
+      //           .having((e) => e.origin, 'origin', provider.stream),
+      //     ]),
+      //   );
+      // });
 
       test('when using provider.overrideWithProvider', () async {
         final provider = StreamProvider.autoDispose((ref) => Stream.value(0));
         final root = createContainer();
         final container = createContainer(parent: root, overrides: [
           provider.overrideWithProvider(
-            FutureProvider.autoDispose((ref) async => 42),
+            StreamProvider.autoDispose((ref) => Stream.value(42)),
           ),
         ]);
 
@@ -271,10 +267,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.future),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider.stream),
           ]),
         );
       });
diff --git a/packages/riverpod/test/providers/stream_provider/stream_provider_family_test.dart b/packages/riverpod/test/providers/stream_provider/stream_provider_family_test.dart
index da3c4f9d65..c25fb4bf34 100644
--- a/packages/riverpod/test/providers/stream_provider/stream_provider_family_test.dart
+++ b/packages/riverpod/test/providers/stream_provider/stream_provider_family_test.dart
@@ -11,17 +11,6 @@ void main() {
 
       expect(provider(0).from, provider);
       expect(provider(0).argument, 0);
-
-      expect(provider(0).future.from, provider);
-      expect(provider(0).future.argument, 0);
-
-      expect(provider(0).stream.from, provider);
-      expect(provider(0).stream.argument, 0);
-
-      // ignore: deprecated_member_use_from_same_package
-      expect(provider(0).last.from, provider);
-      // ignore: deprecated_member_use_from_same_package
-      expect(provider(0).last.argument, 0);
     });
 
     group('scoping an override overrides all the associated subproviders', () {
@@ -40,10 +29,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).future),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).stream),
           ]),
         );
       });
@@ -67,10 +52,6 @@ void main() {
           unorderedEquals(<Object?>[
             isA<ProviderElementBase>()
                 .having((e) => e.origin, 'origin', provider(0)),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).future),
-            isA<ProviderElementBase>()
-                .having((e) => e.origin, 'origin', provider(0).stream),
           ]),
         );
       });
diff --git a/packages/riverpod/test/providers/stream_provider/stream_provider_test.dart b/packages/riverpod/test/providers/stream_provider/stream_provider_test.dart
index 3e03d2360d..d5a98e6823 100644
--- a/packages/riverpod/test/providers/stream_provider/stream_provider_test.dart
+++ b/packages/riverpod/test/providers/stream_provider/stream_provider_test.dart
@@ -11,6 +11,7 @@ void main() {
   final provider = StreamProvider((ref) => controller.stream);
   late ProviderContainer container;
 
+  // TODO remove this setup/teardown
   setUp(() {
     container = createContainer();
     controller = StreamController<int>(sync: true);
@@ -158,43 +159,40 @@ void main() {
         unorderedEquals(<Object?>[
           isA<ProviderElementBase>()
               .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.future),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.stream),
         ]),
       );
     });
 
-    test('when using provider.overrideWithValue', () async {
-      final provider = StreamProvider((ref) => Stream.value(0));
-      final root = createContainer();
-      final container = createContainer(parent: root, overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
-
-      expect(await container.read(provider.stream).first, 42);
-      expect(await container.read(provider.future), 42);
-      expect(container.read(provider), const AsyncValue.data(42));
-      expect(root.getAllProviderElements(), isEmpty);
-      expect(
-        container.getAllProviderElements(),
-        unorderedEquals(<Object?>[
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.future),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.stream),
-        ]),
-      );
-    });
+    // test('when using provider.overrideWithValue', () async {
+    //   final provider = StreamProvider((ref) => Stream.value(0));
+    //   final root = createContainer();
+    //   final container = createContainer(parent: root, overrides: [
+    //     provider.overrideWithValue(const AsyncValue.data(42)),
+    //   ]);
+
+    //   expect(await container.read(provider.stream).first, 42);
+    //   expect(await container.read(provider.future), 42);
+    //   expect(container.read(provider), const AsyncValue.data(42));
+    //   expect(root.getAllProviderElements(), isEmpty);
+    //   expect(
+    //     container.getAllProviderElements(),
+    //     unorderedEquals(<Object?>[
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider),
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider.future),
+    //       isA<ProviderElementBase>()
+    //           .having((e) => e.origin, 'origin', provider.stream),
+    //     ]),
+    //   );
+    // });
 
     test('when using provider.overrideWithProvider', () async {
       final provider = StreamProvider((ref) => Stream.value(0));
       final root = createContainer();
       final container = createContainer(parent: root, overrides: [
-        provider.overrideWithProvider(FutureProvider((ref) async => 42)),
+        provider
+            .overrideWithProvider(StreamProvider((ref) => Stream.value(42))),
       ]);
 
       expect(await container.read(provider.stream).first, 42);
@@ -206,10 +204,6 @@ void main() {
         unorderedEquals(<Object?>[
           isA<ProviderElementBase>()
               .having((e) => e.origin, 'origin', provider),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.future),
-          isA<ProviderElementBase>()
-              .having((e) => e.origin, 'origin', provider.stream),
         ]),
       );
     });
@@ -230,208 +224,210 @@ void main() {
     controller.addError(42, stack);
 
     expect(
-        container.read(provider), AsyncValue<int>.error(42, stackTrace: stack));
+      container.read(provider),
+      AsyncValue<int>.error(42, stackTrace: stack),
+    );
   });
 
   group('.future', () {
-    test(
-        'throws StateError if the provider is disposed before a value was emitted',
-        () async {
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncLoading()),
-      ]);
+    // test(
+    //     'throws StateError if the provider is disposed before a value was emitted',
+    //     () async {
+    //   final container = createContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncLoading()),
+    //   ]);
 
-      final future = container.read(provider.future);
+    //   final future = container.read(provider.future);
 
-      container.dispose();
+    //   container.dispose();
 
-      await expectLater(
-        future,
-        throwsA(
-          isA<StateError>().having(
-            (e) => e.message,
-            'message',
-            equalsIgnoringHashCodes(
-              'The provider StreamProvider<int>#00000 was disposed before a value was emitted.',
-            ),
-          ),
-        ),
-      );
-    });
+    //   await expectLater(
+    //     future,
+    //     throwsA(
+    //       isA<StateError>().having(
+    //         (e) => e.message,
+    //         'message',
+    //         equalsIgnoringHashCodes(
+    //           'The provider StreamProvider<int>#00000 was disposed before a value was emitted.',
+    //         ),
+    //       ),
+    //     ),
+    //   );
+    // });
 
-    test('supports loading then error then loading', () async {
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncLoading()),
-      ]);
+    //   test('supports loading then error then loading', () async {
+    //     final container = createContainer(overrides: [
+    //       provider.overrideWithValue(const AsyncLoading()),
+    //     ]);
 
-      var future = container.read(provider.future);
+    //     var future = container.read(provider.future);
 
-      final error = Error();
+    //     final error = Error();
 
-      container.updateOverrides([
-        provider.overrideWithValue(AsyncValue.error(error)),
-      ]);
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(AsyncValue.error(error)),
+    //     ]);
 
-      expect(container.read(provider.future), future);
+    //     expect(container.read(provider.future), future);
 
-      // TODO(rrousselGit) test that the stacktrace is preserved
-      await expectLater(future, throwsA(error));
+    //     // TODO(rrousselGit) test that the stacktrace is preserved
+    //     await expectLater(future, throwsA(error));
 
-      final error2 = Error();
+    //     final error2 = Error();
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.loading()),
-      ]);
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(const AsyncValue.loading()),
+    //     ]);
 
-      future = container.read(provider.future);
+    //     future = container.read(provider.future);
 
-      container.updateOverrides([
-        provider.overrideWithValue(AsyncValue.error(error2)),
-      ]);
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(AsyncValue.error(error2)),
+    //     ]);
 
-      expect(container.read(provider.future), future);
+    //     expect(container.read(provider.future), future);
 
-      // TODO(rrousselGit) test that the stacktrace is preserved
-      await expectLater(future, throwsA(error2));
-    });
+    //     // TODO(rrousselGit) test that the stacktrace is preserved
+    //     await expectLater(future, throwsA(error2));
+    //   });
 
-    test('supports loading then error then another error', () async {
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncLoading()),
-      ]);
+    //   test('supports loading then error then another error', () async {
+    //     final container = createContainer(overrides: [
+    //       provider.overrideWithValue(const AsyncLoading()),
+    //     ]);
 
-      var future = container.read(provider.future);
+    //     var future = container.read(provider.future);
 
-      final error = Error();
+    //     final error = Error();
 
-      container.updateOverrides([
-        provider.overrideWithValue(AsyncValue.error(error)),
-      ]);
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(AsyncValue.error(error)),
+    //     ]);
 
-      expect(container.read(provider.future), future);
+    //     expect(container.read(provider.future), future);
 
-      // TODO(rrousselGit) test that the stacktrace is preserved
-      await expectLater(future, throwsA(error));
+    //     // TODO(rrousselGit) test that the stacktrace is preserved
+    //     await expectLater(future, throwsA(error));
 
-      final error2 = Error();
+    //     final error2 = Error();
 
-      // error without passing by an intermediary loading state
-      container.updateOverrides([
-        provider.overrideWithValue(AsyncValue.error(error2)),
-      ]);
+    //     // error without passing by an intermediary loading state
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(AsyncValue.error(error2)),
+    //     ]);
 
-      future = container.read(provider.future);
+    //     future = container.read(provider.future);
 
-      // TODO(rrousselGit) test that the stacktrace is preserved
-      await expectLater(future, throwsA(error2));
-    });
+    //     // TODO(rrousselGit) test that the stacktrace is preserved
+    //     await expectLater(future, throwsA(error2));
+    //   });
 
-    test('supports loading then data then loading', () async {
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncLoading()),
-      ]);
+    //   test('supports loading then data then loading', () async {
+    //     final container = createContainer(overrides: [
+    //       provider.overrideWithValue(const AsyncLoading()),
+    //     ]);
 
-      var future = container.read(provider.future);
+    //     var future = container.read(provider.future);
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(const AsyncValue.data(42)),
+    //     ]);
 
-      expect(container.read(provider.future), future);
-      await expectLater(future, completion(42));
+    //     expect(container.read(provider.future), future);
+    //     await expectLater(future, completion(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.loading()),
-      ]);
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(const AsyncValue.loading()),
+    //     ]);
 
-      future = container.read(provider.future);
+    //     future = container.read(provider.future);
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(21)),
-      ]);
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(const AsyncValue.data(21)),
+    //     ]);
 
-      expect(container.read(provider.future), future);
-      await expectLater(future, completion(21));
-    });
+    //     expect(container.read(provider.future), future);
+    //     await expectLater(future, completion(21));
+    //   });
 
-    test('supports loading then data then another data', () async {
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncLoading()),
-      ]);
+    //   test('supports loading then data then another data', () async {
+    //     final container = createContainer(overrides: [
+    //       provider.overrideWithValue(const AsyncLoading()),
+    //     ]);
 
-      var future = container.read(provider.future);
+    //     var future = container.read(provider.future);
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(const AsyncValue.data(42)),
+    //     ]);
 
-      expect(container.read(provider.future), future);
-      await expectLater(future, completion(42));
+    //     expect(container.read(provider.future), future);
+    //     await expectLater(future, completion(42));
 
-      // data without passing by an intermediary loading state
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(21)),
-      ]);
+    //     // data without passing by an intermediary loading state
+    //     container.updateOverrides([
+    //       provider.overrideWithValue(const AsyncValue.data(21)),
+    //     ]);
 
-      future = container.read(provider.future);
+    //     future = container.read(provider.future);
 
-      await expectLater(future, completion(21));
-    });
+    //     await expectLater(future, completion(21));
+    //   });
   });
 
-  test('myProvider.stream emits done on dispose', () async {
-    final stream = container.read(provider.stream);
+  // test('myProvider.stream emits done on dispose', () async {
+  //   final stream = container.read(provider.stream);
 
-    container.dispose();
+  //   container.dispose();
 
-    await expectLater(stream, emitsDone);
-  });
+  //   await expectLater(stream, emitsDone);
+  // });
 
-  test('myProvider.stream re-create a new stream when re-entering loading',
-      () async {
-    final container = createContainer(overrides: [
-      provider.overrideWithValue(const AsyncValue.data(42)),
-    ]);
+  // test('myProvider.stream re-create a new stream when re-entering loading',
+  //     () async {
+  //   final container = createContainer(overrides: [
+  //     provider.overrideWithValue(const AsyncValue.data(42)),
+  //   ]);
 
-    final stream = container.read(provider.stream);
+  //   final stream = container.read(provider.stream);
 
-    await expectLater(stream, emits(42));
+  //   await expectLater(stream, emits(42));
 
-    container.updateOverrides([
-      provider.overrideWithValue(const AsyncValue.loading()),
-    ]);
+  //   container.updateOverrides([
+  //     provider.overrideWithValue(const AsyncValue.loading()),
+  //   ]);
 
-    final stream2 = container.read(provider.stream);
+  //   final stream2 = container.read(provider.stream);
 
-    expect(stream2, isNot(stream));
-    await expectLater(stream, emitsDone);
+  //   expect(stream2, isNot(stream));
+  //   await expectLater(stream, emitsDone);
 
-    container.updateOverrides([
-      provider.overrideWithValue(const AsyncValue.data(21)),
-    ]);
+  //   container.updateOverrides([
+  //     provider.overrideWithValue(const AsyncValue.data(21)),
+  //   ]);
 
-    await expectLater(stream2, emits(21));
+  //   await expectLater(stream2, emits(21));
 
-    container.dispose();
+  //   container.dispose();
 
-    await expectLater(stream2, emitsDone);
-  });
+  //   await expectLater(stream2, emitsDone);
+  // });
 
-  test('myProvider.stream works across provider rebuild', () async {
-    final container = createContainer(overrides: [
-      provider.overrideWithValue(const AsyncValue.data(42)),
-    ]);
+  // test('myProvider.stream works across provider rebuild', () async {
+  //   final container = createContainer(overrides: [
+  //     provider.overrideWithValue(const AsyncValue.data(42)),
+  //   ]);
 
-    final stream = container.read(provider.stream);
+  //   final stream = container.read(provider.stream);
 
-    await expectLater(stream, emits(42));
+  //   await expectLater(stream, emits(42));
 
-    container.updateOverrides(
-      [provider.overrideWithValue(const AsyncValue.data(21))],
-    );
+  //   container.updateOverrides(
+  //     [provider.overrideWithValue(const AsyncValue.data(21))],
+  //   );
 
-    await expectLater(stream, emits(21));
-  });
+  //   await expectLater(stream, emits(21));
+  // });
 
   test('does not filter identical values', () async {
     final sub = container.listen(provider, (_, __) {});
@@ -535,82 +531,82 @@ void main() {
   });
 
   group('overrideWithValue(T)', () {
-    test('.stream is a broadcast stream', () async {
-      final provider = StreamProvider((ref) => controller.stream);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue<int>.data(42)),
-      ]);
-
-      final sub = container.listen(provider.stream, (_, __) {});
-
-      await expectLater(sub.read(), emits(42));
-
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue<int>.data(21)),
-      ]);
-
-      await expectLater(sub.read(), emits(21));
-    });
-
-    test('.stream queues events when there are no listeners', () async {
-      final provider = StreamProvider((ref) => controller.stream);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue<int>.data(42)),
-      ]);
-
-      final sub = container.listen(provider.stream, (_, __) {});
-
-      await expectLater(sub.read(), emits(42));
-
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue<int>.data(21)),
-      ]);
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue<int>.data(22)),
-      ]);
-
-      // This await would normally prevent the test from reading the "21" event
-      // unless the event is queued
-      await container.pump();
-
-      await expectLater(
-        sub.read(),
-        emitsInOrder(<Object?>[21, 22]),
-      );
-    });
-
-    test('.stream emits done when the container is disposed', () async {
-      final provider = StreamProvider.autoDispose((ref) => controller.stream);
-      final container = createContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue<int>.data(42)),
-      ]);
-
-      final sub = container.listen(provider.stream, (_, __) {});
-
-      final stream = sub.read();
-
-      container.dispose();
-
-      await expectLater(stream, emits(42));
-      await expectLater(stream, emitsDone);
-    });
-  });
-
-  test(
-      'when overridden with an error but provider.stream is not listened to, it should not emit an error to the zone',
-      () async {
-    final error = Error();
-    final stream = StreamProvider<int>((ref) => const Stream.empty());
-
-    final container = ProviderContainer(overrides: [
-      stream.overrideWithValue(AsyncValue.error(error)),
-    ]);
-    addTearDown(container.dispose);
-
-    expect(
-      container.read(stream),
-      AsyncValue<int>.error(error),
-    );
+    // test('.stream is a broadcast stream', () async {
+    //   final provider = StreamProvider((ref) => controller.stream);
+    //   final container = createContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncValue<int>.data(42)),
+    //   ]);
+
+    //   final sub = container.listen(provider.stream, (_, __) {});
+
+    //   await expectLater(sub.read(), emits(42));
+
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue<int>.data(21)),
+    //   ]);
+
+    //   await expectLater(sub.read(), emits(21));
+    // });
+
+    // test('.stream queues events when there are no listeners', () async {
+    //   final provider = StreamProvider((ref) => controller.stream);
+    //   final container = createContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncValue<int>.data(42)),
+    //   ]);
+
+    //   final sub = container.listen(provider.stream, (_, __) {});
+
+    //   await expectLater(sub.read(), emits(42));
+
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue<int>.data(21)),
+    //   ]);
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue<int>.data(22)),
+    //   ]);
+
+    //   // This await would normally prevent the test from reading the "21" event
+    //   // unless the event is queued
+    //   await container.pump();
+
+    //   await expectLater(
+    //     sub.read(),
+    //     emitsInOrder(<Object?>[21, 22]),
+    //   );
+    // });
+
+    //   test('.stream emits done when the container is disposed', () async {
+    //     final provider = StreamProvider.autoDispose((ref) => controller.stream);
+    //     final container = createContainer(overrides: [
+    //       provider.overrideWithValue(const AsyncValue<int>.data(42)),
+    //     ]);
+
+    //     final sub = container.listen(provider.stream, (_, __) {});
+
+    //     final stream = sub.read();
+
+    //     container.dispose();
+
+    //     await expectLater(stream, emits(42));
+    //     await expectLater(stream, emitsDone);
+    //   });
+    // });
+
+    // test(
+    //     'when overridden with an error but provider.stream is not listened to, it should not emit an error to the zone',
+    //     () async {
+    //   final error = Error();
+    //   final stream = StreamProvider<int>((ref) => const Stream.empty());
+
+    //   final container = ProviderContainer(overrides: [
+    //     stream.overrideWithValue(AsyncValue.error(error)),
+    //   ]);
+    //   addTearDown(container.dispose);
+
+    //   expect(
+    //     container.read(stream),
+    //     AsyncValue<int>.error(error),
+    //   );
   });
 
   test('StreamProvider.family', () async {
@@ -770,108 +766,37 @@ void main() {
       expect(callCount, 1);
     });
 
-    test('update dependents when the stream changes', () async {
-      final streamProvider = StateProvider((ref) => Stream.value(42));
+    test('.stream creates the stream once and it contains all events',
+        () async {
+      final currentStream = StateProvider((ref) => Stream.value(42));
       // a StreamProvider that can rebuild with a new future
-      final provider =
-          StreamProvider((ref) => ref.watch(streamProvider.state).state);
-      var callCount = 0;
-      final dependent = Provider((ref) {
-        callCount++;
-        return ref.watch(provider.stream);
-      });
+      final streamProvider = StreamProvider((ref) => ref.watch(currentStream));
       final container = createContainer();
-      final streamController = container.read(streamProvider.state);
-
-      await expectLater(container.read(dependent), emits(42));
-      expect(callCount, 1);
-
-      streamController.state = Stream.value(21);
+      final listener = Listener<Stream<int>>();
 
-      await expectLater(container.read(dependent), emits(21));
-      expect(callCount, 2);
-    });
-
-    test('.name is the listened-to name.stream', () {
-      expect(
-        StreamProvider<int>((ref) async* {}, name: 'hey').stream.name,
-        'hey.stream',
-      );
-      expect(
-        StreamProvider<int>((ref) async* {}).stream.name,
-        null,
-      );
-    });
-
-    test('.name is the listened-to name.future', () {
-      expect(
-        StreamProvider<int>((ref) async* {}, name: 'hey').future.name,
-        'hey.future',
-      );
-      expect(
-        StreamProvider<int>((ref) async* {}).stream.name,
-        null,
-      );
-    });
-  });
-
-  group('StreamProvider.autoDispose().stream', () {
-    test('.name is the listened-to name.stream', () {
-      expect(
-        StreamProvider.autoDispose<int>((ref) async* {}, name: 'hey')
-            .stream
-            .name,
-        'hey.stream',
-      );
-      expect(
-        StreamProvider.autoDispose<int>((ref) async* {}).stream.name,
-        null,
-      );
-    });
-
-    test('.name is the listened-to name.future', () {
-      expect(
-        StreamProvider.autoDispose<int>((ref) async* {}, name: 'hey')
-            .future
-            .name,
-        'hey.future',
-      );
-      expect(
-        StreamProvider.autoDispose<int>((ref) async* {}).stream.name,
-        null,
+      final sub = container.listen(
+        streamProvider.stream,
+        listener,
+        fireImmediately: true,
       );
-    });
-
-    test('update dependents when the stream changes', () async {
-      final streamStateProvider =
-          StateProvider((ref) => Stream.value(42), name: 'stateProvider');
-      // a StreamProvider that can rebuild with a new future
-      final streamProvider = StreamProvider.autoDispose((ref) {
-        return ref.watch(streamStateProvider.state).state;
-      }, name: 'streamProvider');
-      var callCount = 0;
-      final dependent = Provider.autoDispose((ref) {
-        callCount++;
-        return ref.watch(streamProvider.stream);
-      }, name: 'dependent');
-      final container = createContainer();
 
-      final streamController = container.read(streamStateProvider.state);
-      container.read(streamProvider.stream);
-      final sub = container.listen(dependent, (_, __) {});
+      final stream = sub.read();
 
-      await expectLater(sub.read(), emits(42));
-      expect(callCount, 1);
+      verifyOnly(listener, listener(null, sub.read()));
+      await expectLater(stream, emits(42));
 
-      streamController.state = Stream.value(21);
+      container.read(currentStream.notifier).state = Stream.value(21);
+      await expectLater(stream, emits(21));
 
-      final stream = sub.read();
-      container.read(streamProvider.stream);
+      // Making sure providers are disposed, sending done events to ".stream".
+      container.dispose();
 
-      expect(callCount, 2);
-      await expectLater(stream, emits(21));
+      await expectLater(stream, emitsDone);
+      verifyNoMoreInteractions(listener);
     });
+  });
 
+  group('StreamProvider.autoDispose().stream', () {
     test('does not update dependents when the future completes', () async {
       final controller = StreamController<int>(sync: true);
       addTearDown(controller.close);
@@ -978,76 +903,76 @@ void main() {
     });
 
     group('from StreamProvider.overrideWithValue', () {
-      test('read currentValue before first value', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('read currentValue before first value', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        final future = container.read(provider.future);
+      //     final future = container.read(provider.future);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.data(42)),
+      //     ]);
 
-        await expectLater(future, completion(42));
-      });
+      //     await expectLater(future, completion(42));
+      //   });
 
-      test('read currentValue before after value', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('read currentValue before after value', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.data(42)),
+      //     ]);
 
-        final future = container.read(provider.future);
+      //     final future = container.read(provider.future);
 
-        await expectLater(future, completion(42));
-      });
+      //     await expectLater(future, completion(42));
+      //   });
 
-      test('read currentValue before first error', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('read currentValue before first error', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        final future = container.read(provider.future);
+      //     final future = container.read(provider.future);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.error(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.error(42)),
+      //     ]);
 
-        await expectLater(future, throwsA(42));
-      });
+      //     await expectLater(future, throwsA(42));
+      //   });
 
-      test('read currentValue before after error', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('read currentValue before after error', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.error(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.error(42)),
+      //     ]);
 
-        final future = container.read(provider.future);
+      //     final future = container.read(provider.future);
 
-        await expectLater(future, throwsA(42));
-      });
+      //     await expectLater(future, throwsA(42));
+      //   });
 
-      test('synchronous first event', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
+      //   test('synchronous first event', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.data(42)),
+      //     ]);
 
-        final future = container.read(provider.future);
+      //     final future = container.read(provider.future);
 
-        await expectLater(future, completion(42));
-      });
+      //     await expectLater(future, completion(42));
+      //   });
     });
   });
 
@@ -1111,483 +1036,483 @@ void main() {
     });
 
     group('from StreamProvider.overrideWithValue', () {
-      test('loading to data to loading creates a new stream too', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('loading to data to loading creates a new stream too', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        final stream0 = container.read(provider.stream);
+      //     final stream0 = container.read(provider.stream);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.data(42)),
+      //     ]);
 
-        final stream1 = container.read(provider.stream);
+      //     final stream1 = container.read(provider.stream);
 
-        expect(stream0, stream1);
-        await expectLater(stream1, emits(42));
+      //     expect(stream0, stream1);
+      //     await expectLater(stream1, emits(42));
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        final stream2 = container.read(provider.stream);
+      //     final stream2 = container.read(provider.stream);
 
-        expect(stream2, isNot(stream1));
-        await expectLater(stream1, emitsDone);
+      //     expect(stream2, isNot(stream1));
+      //     await expectLater(stream1, emitsDone);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.data(21)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.data(21)),
+      //     ]);
 
-        await expectLater(stream2, emits(21));
-      });
+      //     await expectLater(stream2, emits(21));
+      //   });
 
-      test('data to loading creates a new stream', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
+      //   test('data to loading creates a new stream', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.data(42)),
+      //     ]);
 
-        final stream1 = container.read(provider.stream);
+      //     final stream1 = container.read(provider.stream);
 
-        await expectLater(stream1, emits(42));
+      //     await expectLater(stream1, emits(42));
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        final stream2 = container.read(provider.stream);
+      //     final stream2 = container.read(provider.stream);
 
-        expect(stream2, isNot(stream1));
-        await expectLater(stream1, emitsDone);
+      //     expect(stream2, isNot(stream1));
+      //     await expectLater(stream1, emitsDone);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.data(21)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.data(21)),
+      //     ]);
 
-        await expectLater(stream2, emits(21));
-      });
+      //     await expectLater(stream2, emits(21));
+      //   });
 
-      test('error to loading creates a new stream', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.error(42)),
-        ]);
+      //   test('error to loading creates a new stream', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.error(42)),
+      //     ]);
 
-        final stream1 = container.read(provider.stream);
+      //     final stream1 = container.read(provider.stream);
 
-        await expectLater(stream1, emitsError(42));
+      //     await expectLater(stream1, emitsError(42));
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        final stream2 = container.read(provider.stream);
+      //     final stream2 = container.read(provider.stream);
 
-        expect(stream2, isNot(stream1));
-        await expectLater(stream1, emitsDone);
+      //     expect(stream2, isNot(stream1));
+      //     await expectLater(stream1, emitsDone);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.data(21)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.data(21)),
+      //     ]);
 
-        await expectLater(stream2, emits(21));
-      });
+      //     await expectLater(stream2, emits(21));
+      //   });
 
-      test('read currentValue before first value', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('read currentValue before first value', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        final stream = container.read(provider.stream);
+      //     final stream = container.read(provider.stream);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.data(42)),
+      //     ]);
 
-        await expectLater(stream, emits(42));
-      });
+      //     await expectLater(stream, emits(42));
+      //   });
 
-      test('read currentValue before after value', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('read currentValue before after value', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.data(42)),
+      //     ]);
 
-        final stream = container.read(provider.stream);
+      //     final stream = container.read(provider.stream);
 
-        await expectLater(stream, emits(42));
-      });
+      //     await expectLater(stream, emits(42));
+      //   });
 
-      test('read currentValue before first error', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('read currentValue before first error', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        final stream = container.read(provider.stream);
+      //     final stream = container.read(provider.stream);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.error(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.error(42)),
+      //     ]);
 
-        await expectLater(stream, emitsError(42));
-      });
+      //     await expectLater(stream, emitsError(42));
+      //   });
 
-      test('read currentValue before after error', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.loading()),
-        ]);
+      //   test('read currentValue before after error', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.loading()),
+      //     ]);
 
-        container.updateOverrides([
-          provider.overrideWithValue(const AsyncValue.error(42)),
-        ]);
+      //     container.updateOverrides([
+      //       provider.overrideWithValue(const AsyncValue.error(42)),
+      //     ]);
 
-        final stream = container.read(provider.stream);
+      //     final stream = container.read(provider.stream);
 
-        await expectLater(stream, emitsError(42));
-      });
+      //     await expectLater(stream, emitsError(42));
+      //   });
 
-      test('synchronous first event', () async {
-        final provider = StreamProvider<int>((_) async* {});
-        final container = ProviderContainer(overrides: [
-          provider.overrideWithValue(const AsyncValue.data(42)),
-        ]);
+      //   test('synchronous first event', () async {
+      //     final provider = StreamProvider<int>((_) async* {});
+      //     final container = ProviderContainer(overrides: [
+      //       provider.overrideWithValue(const AsyncValue.data(42)),
+      //     ]);
 
-        final stream = container.read(provider.stream);
+      //     final stream = container.read(provider.stream);
 
-        await expectLater(stream, emits(42));
-      });
+      //     await expectLater(stream, emits(42));
+      //   });
     });
   });
 
   group('mock as value', () {
-    test('value immediately then other value', () async {
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
-      final stream = container.read(provider.stream);
+    // test('value immediately then other value', () async {
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncValue.data(42)),
+    //   ]);
+    //   final stream = container.read(provider.stream);
 
-      final sub = container.listen(provider, (_, __) {});
+    //   final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue.data(42));
-      await expectLater(stream, emits(42));
+    //   expect(sub.read(), const AsyncValue.data(42));
+    //   await expectLater(stream, emits(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(21)),
-      ]);
-
-      expect(sub.read(), const AsyncValue.data(21));
-      await expectLater(stream, emits(21));
-
-      container.dispose();
-
-      await expectLater(stream, emitsDone);
-    });
-
-    test('value immediately then error', () async {
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
-      final stream = container.read(provider.stream);
-
-      final sub = container.listen(provider, (_, __) {});
-
-      expect(sub.read(), const AsyncValue.data(42));
-      await expectLater(stream, emits(42));
-
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.error(21)),
-      ]);
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue.data(21)),
+    //   ]);
 
-      expect(
-        sub.read(),
-        const AsyncValue<int>.error(21).copyWithPrevious(const AsyncData(42)),
-      );
-      // TODO why call "read" twice?
-      expect(
-        sub.read(),
-        const AsyncValue<int>.error(21).copyWithPrevious(const AsyncData(42)),
-      );
-      await expectLater(stream, emitsError(21));
+    //   expect(sub.read(), const AsyncValue.data(21));
+    //   await expectLater(stream, emits(21));
 
-      container.dispose();
+    //   container.dispose();
 
-      await expectLater(stream, emitsDone);
-    });
+    //   await expectLater(stream, emitsDone);
+    // });
 
-    test('value immediately then loading', () async {
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
-      final stream = container.read(provider.stream);
+    // test('value immediately then error', () async {
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncValue.data(42)),
+    //   ]);
+    //   final stream = container.read(provider.stream);
 
-      final sub = container.listen(provider, (_, __) {});
+    //   final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue.data(42));
-      await expectLater(stream, emits(42));
+    //   expect(sub.read(), const AsyncValue.data(42));
+    //   await expectLater(stream, emits(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue<int>.loading()),
-      ]);
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue.error(21)),
+    //   ]);
 
-      expect(
-        sub.read(),
-        const AsyncLoading<int>()
-            .copyWithPrevious(const AsyncValue<int>.data(42)),
-      );
+    //   expect(
+    //     sub.read(),
+    //     const AsyncValue<int>.error(21).copyWithPrevious(const AsyncData(42)),
+    //   );
+    //   // TODO why call "read" twice?
+    //   expect(
+    //     sub.read(),
+    //     const AsyncValue<int>.error(21).copyWithPrevious(const AsyncData(42)),
+    //   );
+    //   await expectLater(stream, emitsError(21));
 
-      container.dispose();
+    //   container.dispose();
 
-      await expectLater(stream, emitsDone);
-    });
+    //   await expectLater(stream, emitsDone);
+    // });
 
-    test('loading immediately then value', () async {
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue<int>.loading()),
-      ]);
-      final stream = container.read(provider.stream);
+    // test('value immediately then loading', () async {
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncValue.data(42)),
+    //   ]);
+    //   final stream = container.read(provider.stream);
 
-      final sub = container.listen(provider, (_, __) {});
+    //   final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue<int>.loading());
+    //   expect(sub.read(), const AsyncValue.data(42));
+    //   await expectLater(stream, emits(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue<int>.loading()),
+    //   ]);
 
-      expect(sub.read(), const AsyncValue.data(42));
-      await expectLater(stream, emits(42));
+    //   expect(
+    //     sub.read(),
+    //     const AsyncLoading<int>()
+    //         .copyWithPrevious(const AsyncValue<int>.data(42)),
+    //   );
 
-      container.dispose();
+    //   container.dispose();
 
-      await expectLater(stream, emitsDone);
-    });
+    //   await expectLater(stream, emitsDone);
+    // });
 
-    test('loading immediately then error', () async {
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue<int>.loading()),
-      ]);
-      final stream = container.read(provider.stream);
+    // test('loading immediately then value', () async {
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncValue<int>.loading()),
+    //   ]);
+    //   final stream = container.read(provider.stream);
 
-      final sub = container.listen(provider, (_, __) {});
+    //   final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), const AsyncValue<int>.loading());
+    //   expect(sub.read(), const AsyncValue<int>.loading());
 
-      final stackTrace = StackTrace.current;
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue.data(42)),
+    //   ]);
 
-      container.updateOverrides([
-        provider.overrideWithValue(
-            AsyncValue<int>.error(42, stackTrace: stackTrace)),
-      ]);
+    //   expect(sub.read(), const AsyncValue.data(42));
+    //   await expectLater(stream, emits(42));
 
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+    //   container.dispose();
 
-      await expectLater(stream, emitsError(42));
+    //   await expectLater(stream, emitsDone);
+    // });
 
-      container.dispose();
+    // test('loading immediately then error', () async {
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncValue<int>.loading()),
+    //   ]);
+    //   final stream = container.read(provider.stream);
 
-      await expectLater(stream, emitsDone);
-    });
+    //   final sub = container.listen(provider, (_, __) {});
 
-    test('loading immediately then loading', () async {
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(const AsyncValue<int>.loading()),
-      ]);
-      final stream = container.read(provider.stream);
-      final listener = Listener<AsyncValue<int>>();
+    //   expect(sub.read(), const AsyncValue<int>.loading());
 
-      container.listen(provider, listener, fireImmediately: true);
+    //   final stackTrace = StackTrace.current;
 
-      verifyOnly(listener, listener(null, const AsyncValue<int>.loading()));
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(
+    //         AsyncValue<int>.error(42, stackTrace: stackTrace)),
+    //   ]);
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue<int>.loading()),
-      ]);
+    //   expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
 
-      verifyNoMoreInteractions(listener);
+    //   await expectLater(stream, emitsError(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(42)),
-      ]);
+    //   container.dispose();
 
-      verifyOnly(
-        listener,
-        listener(const AsyncValue.loading(), const AsyncValue<int>.data(42)),
-      );
+    //   await expectLater(stream, emitsDone);
+    // });
 
-      await expectLater(stream, emits(42));
+    // test('loading immediately then loading', () async {
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(const AsyncValue<int>.loading()),
+    //   ]);
+    //   final stream = container.read(provider.stream);
+    //   final listener = Listener<AsyncValue<int>>();
 
-      container.dispose();
+    //   container.listen(provider, listener, fireImmediately: true);
 
-      await expectLater(stream, emitsDone);
-    });
+    //   verifyOnly(listener, listener(null, const AsyncValue<int>.loading()));
 
-    test('error immediately then different error', () async {
-      final stackTrace = StackTrace.current;
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(
-            AsyncValue<int>.error(42, stackTrace: stackTrace)),
-      ]);
-      final stream = container.read(provider.stream);
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue<int>.loading()),
+    //   ]);
 
-      final sub = container.listen(provider, (_, __) {});
+    //   verifyNoMoreInteractions(listener);
 
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
-      await expectLater(stream, emitsError(42));
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue.data(42)),
+    //   ]);
 
-      container.updateOverrides([
-        provider.overrideWithValue(
-            AsyncValue<int>.error(21, stackTrace: stackTrace)),
-      ]);
+    //   verifyOnly(
+    //     listener,
+    //     listener(const AsyncValue.loading(), const AsyncValue<int>.data(42)),
+    //   );
 
-      expect(sub.read(), AsyncValue<int>.error(21, stackTrace: stackTrace));
-      await expectLater(stream, emitsError(21));
+    //   await expectLater(stream, emits(42));
 
-      container.dispose();
+    //   container.dispose();
 
-      await expectLater(stream, emitsDone);
-    });
+    //   await expectLater(stream, emitsDone);
+    // });
 
-    test('error immediately then different stacktrace', () async {
-      final stackTrace = StackTrace.current;
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(
-            AsyncValue<int>.error(42, stackTrace: stackTrace)),
-      ]);
-      final stream = container.read(provider.stream);
+    // test('error immediately then different error', () async {
+    //   final stackTrace = StackTrace.current;
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(
+    //         AsyncValue<int>.error(42, stackTrace: stackTrace)),
+    //   ]);
+    //   final stream = container.read(provider.stream);
 
-      final sub = container.listen(provider, (_, __) {});
+    //   final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
-      await expectLater(stream, emitsError(42));
+    //   expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+    //   await expectLater(stream, emitsError(42));
 
-      final stackTrace2 = StackTrace.current;
-      container.updateOverrides([
-        provider.overrideWithValue(
-          AsyncValue<int>.error(42, stackTrace: stackTrace2),
-        ),
-      ]);
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(
+    //         AsyncValue<int>.error(21, stackTrace: stackTrace)),
+    //   ]);
 
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace2));
-      await expectLater(stream, emitsError(42));
+    //   expect(sub.read(), AsyncValue<int>.error(21, stackTrace: stackTrace));
+    //   await expectLater(stream, emitsError(21));
 
-      container.dispose();
+    //   container.dispose();
 
-      await expectLater(stream, emitsDone);
-    });
+    //   await expectLater(stream, emitsDone);
+    // });
 
-    test('error immediately then data', () async {
-      const stackTrace = StackTrace.empty;
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(
-            const AsyncValue<int>.error(42, stackTrace: stackTrace)),
-      ]);
-      final stream = container.read(provider.stream);
+    // test('error immediately then different stacktrace', () async {
+    //   final stackTrace = StackTrace.current;
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(
+    //         AsyncValue<int>.error(42, stackTrace: stackTrace)),
+    //   ]);
+    //   final stream = container.read(provider.stream);
 
-      final sub = container.listen(provider, (_, __) {});
+    //   final sub = container.listen(provider, (_, __) {});
 
-      expect(
-        sub.read(),
-        const AsyncValue<int>.error(42, stackTrace: stackTrace),
-      );
-      await expectLater(stream, emitsError(42));
+    //   expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+    //   await expectLater(stream, emitsError(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue.data(21)),
-      ]);
+    //   final stackTrace2 = StackTrace.current;
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(
+    //       AsyncValue<int>.error(42, stackTrace: stackTrace2),
+    //     ),
+    //   ]);
 
-      expect(
-        sub.read(),
-        const AsyncValue.data(21)
-            .copyWithPrevious(const AsyncError(42, stackTrace: stackTrace)),
-      );
-      await expectLater(stream, emits(21));
+    //   expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace2));
+    //   await expectLater(stream, emitsError(42));
 
-      container.dispose();
+    //   container.dispose();
 
-      await expectLater(stream, emitsDone);
-    });
+    //   await expectLater(stream, emitsDone);
+    // });
 
-    test('error immediately then loading', () async {
-      final stackTrace = StackTrace.current;
-      final provider = StreamProvider<int>((_) async* {});
-      final container = ProviderContainer(overrides: [
-        provider.overrideWithValue(
-            AsyncValue<int>.error(42, stackTrace: stackTrace)),
-      ]);
-      final stream = container.read(provider.stream);
+    // test('error immediately then data', () async {
+    //   const stackTrace = StackTrace.empty;
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(
+    //         const AsyncValue<int>.error(42, stackTrace: stackTrace)),
+    //   ]);
+    //   final stream = container.read(provider.stream);
 
-      final sub = container.listen(provider, (_, __) {});
+    //   final sub = container.listen(provider, (_, __) {});
 
-      expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
-      await expectLater(stream, emitsError(42));
+    //   expect(
+    //     sub.read(),
+    //     const AsyncValue<int>.error(42, stackTrace: stackTrace),
+    //   );
+    //   await expectLater(stream, emitsError(42));
 
-      container.updateOverrides([
-        provider.overrideWithValue(const AsyncValue<int>.loading()),
-      ]);
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue.data(21)),
+    //   ]);
 
-      expect(
-        sub.read(),
-        const AsyncLoading<int>()
-            .copyWithPrevious(AsyncError<int>(42, stackTrace: stackTrace)),
-      );
+    //   expect(
+    //     sub.read(),
+    //     const AsyncValue.data(21)
+    //         .copyWithPrevious(const AsyncError(42, stackTrace: stackTrace)),
+    //   );
+    //   await expectLater(stream, emits(21));
 
-      container.dispose();
+    //   container.dispose();
+
+    //   await expectLater(stream, emitsDone);
+    // });
+
+    // test('error immediately then loading', () async {
+    //   final stackTrace = StackTrace.current;
+    //   final provider = StreamProvider<int>((_) async* {});
+    //   final container = ProviderContainer(overrides: [
+    //     provider.overrideWithValue(
+    //         AsyncValue<int>.error(42, stackTrace: stackTrace)),
+    //   ]);
+    //   final stream = container.read(provider.stream);
+
+    //   final sub = container.listen(provider, (_, __) {});
+
+    //   expect(sub.read(), AsyncValue<int>.error(42, stackTrace: stackTrace));
+    //   await expectLater(stream, emitsError(42));
+
+    //   container.updateOverrides([
+    //     provider.overrideWithValue(const AsyncValue<int>.loading()),
+    //   ]);
 
-      await expectLater(stream, emitsDone);
-    });
+    //   expect(
+    //     sub.read(),
+    //     const AsyncLoading<int>()
+    //         .copyWithPrevious(AsyncError<int>(42, stackTrace: stackTrace)),
+    //   );
+
+    //   container.dispose();
+
+    //   await expectLater(stream, emitsDone);
+    // });
   });
 }
 
-class MockStream<T> extends Mock implements Stream<T> {
-  @override
-  StreamSubscription<T> listen(
-    void Function(T event)? onData, {
-    Function? onError,
-    void Function()? onDone,
-    bool? cancelOnError,
-  }) {
-    return super.noSuchMethod(
-      Invocation.method(
-        #listen,
-        [onData],
-        {
-          #onError: onError,
-          #onDone: onDone,
-          #cancelOnError: cancelOnError,
-        },
-      ),
-      returnValue: MockSubscription<T>(),
-      returnValueForMissingStub: MockSubscription<T>(),
-    ) as StreamSubscription<T>;
-  }
-}
-
-class MockSubscription<T> extends Mock implements StreamSubscription<T> {
-  @override
-  Future<void> cancel() {
-    return super.noSuchMethod(
-      Invocation.method(#cancel, []),
-      returnValue: Future<void>.value(),
-      returnValueForMissingStub: Future<void>.value(),
-    ) as Future<void>;
-  }
-}
+// class MockStream<T> extends Mock implements Stream<T> {
+//   @override
+//   StreamSubscription<T> listen(
+//     void Function(T event)? onData, {
+//     Function? onError,
+//     void Function()? onDone,
+//     bool? cancelOnError,
+//   }) {
+//     return super.noSuchMethod(
+//       Invocation.method(
+//         #listen,
+//         [onData],
+//         {
+//           #onError: onError,
+//           #onDone: onDone,
+//           #cancelOnError: cancelOnError,
+//         },
+//       ),
+//       returnValue: MockSubscription<T>(),
+//       returnValueForMissingStub: MockSubscription<T>(),
+//     ) as StreamSubscription<T>;
+//   }
+// }
+
+// class MockSubscription<T> extends Mock implements StreamSubscription<T> {
+//   @override
+//   Future<void> cancel() {
+//     return super.noSuchMethod(
+//       Invocation.method(#cancel, []),
+//       returnValue: Future<void>.value(),
+//       returnValueForMissingStub: Future<void>.value(),
+//     ) as Future<void>;
+//   }
+// }
diff --git a/packages/riverpod/test/utils.dart b/packages/riverpod/test/utils.dart
index b2a60d4548..215b556273 100644
--- a/packages/riverpod/test/utils.dart
+++ b/packages/riverpod/test/utils.dart
@@ -4,6 +4,8 @@ import 'package:mockito/mockito.dart';
 import 'package:riverpod/riverpod.dart';
 import 'package:test/test.dart';
 
+final isAssertionError = isA<AssertionError>();
+
 R Function(Key) cacheFamily<Key, R>(R Function(Key key) create) {
   final cache = <Key, R>{};
   return (key) => cache.putIfAbsent(key, () => create(key));
diff --git a/website/docs/cookbooks/testing.mdx b/website/docs/cookbooks/testing.mdx
index 30c3019394..e669f92bbd 100644
--- a/website/docs/cookbooks/testing.mdx
+++ b/website/docs/cookbooks/testing.mdx
@@ -124,6 +124,9 @@ For example, [FutureProvider] allows overriding the provider with an `AsyncValue
 
 <CodeBlock>{trimSnippet(testOverrideInfo)}</CodeBlock>
 
+**Note**: As part of the 2.0.0 release, `overrideWithValue` methods are temporarily
+removed. They will be added back in later versions.
+
 :::
 
 :::info
diff --git a/website/docs/cookbooks/testing_override_info.dart b/website/docs/cookbooks/testing_override_info.dart
index 4d722f8c7d..33dc004dd8 100644
--- a/website/docs/cookbooks/testing_override_info.dart
+++ b/website/docs/cookbooks/testing_override_info.dart
@@ -3,6 +3,11 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 
+extension on ProviderBase {
+  // ignore: unused_element
+  Override overrideWithValue(Object? value) => throw UnimplementedError();
+}
+
 class Todo {
   Todo({
     required String id,
@@ -27,7 +32,7 @@ final todoListProvider = FutureProvider((ref) async => <Todo>[]);
 /* SKIP */
 final foo =
 /* SKIP END */
-ProviderScope(
+    ProviderScope(
   overrides: [
     /// Allows overriding a FutureProvider to return a fixed value
     todoListProvider.overrideWithValue(
diff --git a/website/i18n/bn/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart b/website/i18n/bn/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
index 785f9a234b..02f1df5d4c 100644
--- a/website/i18n/bn/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
+++ b/website/i18n/bn/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
@@ -3,6 +3,11 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 
+extension on ProviderBase {
+  // ignore: unused_element
+  Override overrideWithValue(Object? value) => throw UnimplementedError();
+}
+
 class Todo {
   Todo({
     required String id,
diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart b/website/i18n/de/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
index 3cb9945ff2..f2e85d8ceb 100644
--- a/website/i18n/de/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
+++ b/website/i18n/de/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
@@ -3,6 +3,11 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 
+extension on ProviderBase {
+  // ignore: unused_element
+  Override overrideWithValue(Object? value) => throw UnimplementedError();
+}
+
 class Todo {
   Todo({
     required String id,
diff --git a/website/i18n/it/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart b/website/i18n/it/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
index 12b6f357a9..f5693584aa 100644
--- a/website/i18n/it/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
+++ b/website/i18n/it/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
@@ -3,6 +3,11 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 
+extension on ProviderBase {
+  // ignore: unused_element
+  Override overrideWithValue(Object? value) => throw UnimplementedError();
+}
+
 class Todo {
   Todo({
     required String id,
diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart b/website/i18n/ja/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
index 3ebaaa81d8..3ec6d9563c 100644
--- a/website/i18n/ja/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
+++ b/website/i18n/ja/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
@@ -3,6 +3,11 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 
+extension on ProviderBase {
+  // ignore: unused_element
+  Override overrideWithValue(Object? value) => throw UnimplementedError();
+}
+
 class Todo {
   Todo({
     required String id,
@@ -27,7 +32,7 @@ final todoListProvider = FutureProvider((ref) async => <Todo>[]);
 /* SKIP */
 final foo =
 /* SKIP END */
-ProviderScope(
+    ProviderScope(
   overrides: [
     /// FutureProvider をオーバーライドして固定のステートを返す
     todoListProvider.overrideWithValue(
diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart b/website/i18n/ko/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
index 955e4a4b38..0771d70232 100644
--- a/website/i18n/ko/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
+++ b/website/i18n/ko/docusaurus-plugin-content-docs/current/cookbooks/testing_override_info.dart
@@ -3,6 +3,11 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 
+extension on ProviderBase {
+  // ignore: unused_element
+  Override overrideWithValue(Object? value) => throw UnimplementedError();
+}
+
 class Todo {
   Todo({
     required String id,