Skip to content

Cleanup AutoDispose logic #4064

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions examples/pub/lib/detail.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions examples/pub/lib/search.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ abstract class _ChangeNotifierProviderBase<NotifierT extends ChangeNotifier?>
required super.argument,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
});
required super.isAutoDispose,
required DebugGetCreateSourceHash? debugGetCreateSourceHash,
}) : _debugGetCreateSourceHash = debugGetCreateSourceHash;

/// Obtains the [ChangeNotifier] associated with this provider, without listening
/// to state changes.
Expand All @@ -55,6 +56,10 @@ abstract class _ChangeNotifierProviderBase<NotifierT extends ChangeNotifier?>
ProviderListenable<NotifierT> get notifier;

NotifierT _create(covariant ChangeNotifierProviderElement<NotifierT> ref);

final DebugGetCreateSourceHash? _debugGetCreateSourceHash;
@override
String? debugGetCreateSourceHash() => _debugGetCreateSourceHash?.call();
}

/// {@macro riverpod.provider_ref_base}
Expand Down Expand Up @@ -145,6 +150,7 @@ class ChangeNotifierProvider<NotifierT extends ChangeNotifier?>
}) : super(
allTransitiveDependencies:
computeAllTransitiveDependencies(dependencies),
isAutoDispose: false,
);

/// An implementation detail of Riverpod
Expand All @@ -157,6 +163,7 @@ class ChangeNotifierProvider<NotifierT extends ChangeNotifier?>
required super.debugGetCreateSourceHash,
super.from,
super.argument,
super.isAutoDispose = false,
});

/// {@macro riverpod.autoDispose}
Expand Down Expand Up @@ -245,7 +252,9 @@ class ChangeNotifierProviderElement<NotifierT extends ChangeNotifier?>
// ignore: deprecated_member_use, deprecated_member_use_from_same_package
implements
// ignore: deprecated_member_use, deprecated_member_use_from_same_package
ChangeNotifierProviderRef<NotifierT> {
ChangeNotifierProviderRef<NotifierT>,
// ignore: deprecated_member_use, deprecated_member_use_from_same_package
AutoDisposeChangeNotifierProviderRef<NotifierT> {
ChangeNotifierProviderElement._(
_ChangeNotifierProviderBase<NotifierT> super._provider,
);
Expand Down Expand Up @@ -318,6 +327,7 @@ class ChangeNotifierProviderFamily<NotifierT extends ChangeNotifier?, Arg>
debugGetCreateSourceHash: null,
allTransitiveDependencies:
computeAllTransitiveDependencies(dependencies),
isAutoDispose: false,
);

/// {@macro riverpod.override_with}
Expand Down Expand Up @@ -364,6 +374,7 @@ class AutoDisposeChangeNotifierProvider<NotifierT extends ChangeNotifier?>
}) : super(
allTransitiveDependencies:
computeAllTransitiveDependencies(dependencies),
isAutoDispose: true,
);

/// An implementation detail of Riverpod
Expand All @@ -376,6 +387,7 @@ class AutoDisposeChangeNotifierProvider<NotifierT extends ChangeNotifier?>
required super.debugGetCreateSourceHash,
super.from,
super.argument,
super.isAutoDispose = true,
});

/// {@macro riverpod.family}
Expand Down Expand Up @@ -426,25 +438,14 @@ class AutoDisposeChangeNotifierProvider<NotifierT extends ChangeNotifier?>

/// The element of [AutoDisposeChangeNotifierProvider].
@internal
class AutoDisposeChangeNotifierProviderElement<
typedef AutoDisposeChangeNotifierProviderElement<
NotifierT extends ChangeNotifier?>
extends ChangeNotifierProviderElement<NotifierT>
with
AutoDisposeProviderElementMixin<NotifierT>
implements
// ignore: deprecated_member_use_from_same_package
AutoDisposeChangeNotifierProviderRef<NotifierT> {
/// The [ProviderElementBase] for [ChangeNotifier]
@Deprecated('will be removed in 3.0.0, use Ref instead')
AutoDisposeChangeNotifierProviderElement._(
AutoDisposeChangeNotifierProvider<NotifierT> super._provider,
) : super._();
}
= ChangeNotifierProviderElement<NotifierT>;

// ignore: subtype_of_sealed_class
/// The [Family] of [AutoDisposeChangeNotifierProvider].
class AutoDisposeChangeNotifierProviderFamily<NotifierT extends ChangeNotifier?, Arg>
extends AutoDisposeFamilyBase<
extends FamilyBase<
// ignore: deprecated_member_use_from_same_package
AutoDisposeChangeNotifierProviderRef<NotifierT>,
NotifierT,
Expand All @@ -461,6 +462,7 @@ class AutoDisposeChangeNotifierProviderFamily<NotifierT extends ChangeNotifier?,
debugGetCreateSourceHash: null,
allTransitiveDependencies:
computeAllTransitiveDependencies(dependencies),
isAutoDispose: true,
);

/// {@macro riverpod.override_with}
Expand Down
77 changes: 33 additions & 44 deletions packages/riverpod/lib/src/core/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ void Function()? debugCanModifyProviders;
/// {@endtemplate}
@optionalTypeArgs
@internal
abstract class ProviderElementBase<StateT> implements Ref<StateT>, Node {
abstract class ProviderElementBase<StateT>
implements
Ref<StateT>,
// ignore: deprecated_member_use_from_same_package
AutoDisposeRef<StateT>,
Node {
/// {@macro riverpod.provider_element_base}
ProviderElementBase(this._provider);

Expand All @@ -58,6 +63,16 @@ abstract class ProviderElementBase<StateT> implements Ref<StateT>, Node {
String? _debugCurrentCreateHash;
var _debugSkipNotifyListenersAsserts = false;

bool _maintainState = false;
@Deprecated('Use `keepAlive()` instead')
@override
bool get maintainState => _maintainState;
@override
set maintainState(bool value) {
_maintainState = value;
if (!value) mayNeedDispose();
}

/// The provider associated with this [ProviderElementBase], before applying overrides.
// Not typed as <State> because of https://github.com/rrousselGit/riverpod/issues/1100
AnyProvider<Object?> get origin => _origin;
Expand Down Expand Up @@ -924,14 +939,19 @@ The provider ${_debugCurrentlyBuildingElement!.origin} modified $origin while bu
}

/// 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() {}
@mustCallSuper
void mayNeedDispose() {
if (provider.isAutoDispose) {
final links = _keepAliveLinks;

// ignore: deprecated_member_use_from_same_package
if (!maintainState && !hasListeners && (links == null || links.isEmpty)) {
_container.scheduler.scheduleProviderDispose(this);
}
}
}

@override
@mustCallSuper
Expand All @@ -953,6 +973,7 @@ The provider ${_debugCurrentlyBuildingElement!.origin} modified $origin while bu
if (!_mounted) return;
_mounted = false;

_keepAliveLinks?.clear();
final subscriptions = _subscriptions;
if (subscriptions != null) {
while (subscriptions.isNotEmpty) {
Expand Down Expand Up @@ -991,6 +1012,11 @@ The provider ${_debugCurrentlyBuildingElement!.origin} modified $origin while bu
_onChangeSelfListeners = null;
_onErrorSelfListeners = null;
_didCancelOnce = false;

assert(
_keepAliveLinks == null || _keepAliveLinks!.isEmpty,
'Cannot call keepAlive() within onDispose listeners',
);
}

@override
Expand Down Expand Up @@ -1022,40 +1048,3 @@ The provider ${_debugCurrentlyBuildingElement!.origin} modified $origin while bu
return '$runtimeType(provider: $provider, origin: $origin)';
}
}

/// A mixin that adds auto dispose support to a [ProviderElementBase].
@internal
mixin AutoDisposeProviderElementMixin<State> on ProviderElementBase<State>
implements
// ignore: deprecated_member_use_from_same_package
AutoDisposeRef<State> {
bool _maintainState = false;
@Deprecated('Use `keepAlive()` instead')
@override
bool get maintainState => _maintainState;
@override
set maintainState(bool value) {
_maintainState = value;
if (!value) mayNeedDispose();
}

@override
void mayNeedDispose() {
final links = _keepAliveLinks;

// ignore: deprecated_member_use_from_same_package
if (!maintainState && !hasListeners && (links == null || links.isEmpty)) {
_container.scheduler.scheduleProviderDispose(this);
}
}

@override
void runOnDispose() {
_keepAliveLinks?.clear();
super.runOnDispose();
assert(
_keepAliveLinks == null || _keepAliveLinks!.isEmpty,
'Cannot call keepAlive() within onDispose listeners',
);
}
}
Loading
Loading