Skip to content

Commit

Permalink
fix: close ListenManual subscriptions after State.dispose() (#1980)
Browse files Browse the repository at this point in the history
  • Loading branch information
nawafalomari committed Dec 21, 2022
1 parent 97e28b6 commit f6e6e4d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 3 deletions.
1 change: 1 addition & 0 deletions packages/flutter_riverpod/CHANGELOG.md
@@ -1,5 +1,6 @@
## [Unreleased patch]

- It is now correctly possible to use `ProviderSubscription`s inside `ConsumerState.dispose` (thanks to @1980)
- Update dependencies.

## 2.1.1
Expand Down
1 change: 0 additions & 1 deletion packages/flutter_riverpod/example/pubspec.yaml
Expand Up @@ -8,7 +8,6 @@ environment:
sdk: ">=2.17.0 <3.0.0"

dependencies:
cupertino_icons: ^0.1.3
flutter:
sdk: flutter
flutter_riverpod:
Expand Down
6 changes: 4 additions & 2 deletions packages/flutter_riverpod/lib/src/consumer.dart
Expand Up @@ -562,6 +562,10 @@ class ConsumerStatefulElement extends StatefulElement implements WidgetRef {

@override
void unmount() {
/// Calling `super.unmount()` will call `dispose` on the state
/// And [ListenManual] subscriptions should be closed after `dispose`
super.unmount();

for (final dependency in _dependencies.values) {
dependency.close();
}
Expand All @@ -575,8 +579,6 @@ class ConsumerStatefulElement extends StatefulElement implements WidgetRef {
}
_manualListeners = null;
}

super.unmount();
}

@override
Expand Down
41 changes: 41 additions & 0 deletions packages/flutter_riverpod/test/listen_test.dart
Expand Up @@ -9,6 +9,16 @@ import 'utils.dart';

void main() {
group('WidgetRef.listenManual', () {
testWidgets('returns a subscription that can be used within State.dispose',
(tester) async {
await tester.pumpWidget(
const ProviderScope(child: DisposeListenManual()),
);

// Unmounting DisposeListenManual will throw if this is not allowed
await tester.pumpWidget(ProviderScope(child: Container()));
});

testWidgets('listens to changes', (tester) async {
final provider = StateProvider((ref) => 0);
final listener = Listener<int>();
Expand Down Expand Up @@ -368,3 +378,34 @@ void main() {
});
});
}

final _provider = Provider<String>((ref) => '');

class DisposeListenManual extends ConsumerStatefulWidget {
const DisposeListenManual({super.key});

@override
ConsumerState<ConsumerStatefulWidget> createState() =>
_DisposeListenOnceState();
}

class _DisposeListenOnceState extends ConsumerState<DisposeListenManual> {
late final ProviderSubscription<String> sub;

@override
void initState() {
super.initState();
sub = ref.listenManual(_provider, (prev, next) {});
}

@override
Widget build(BuildContext context) {
return Container();
}

@override
void dispose() {
sub.read();
super.dispose();
}
}

0 comments on commit f6e6e4d

Please sign in to comment.