-
-
Notifications
You must be signed in to change notification settings - Fork 956
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
Stream from StreamProvider is not unsubscribed to when widgets get disposed #3562
Comments
I'm having a similar problem |
Theres nothing wrong here. Your provider wasn't disposed. So the Stream is still active. |
Perhaps the test setup is just confusing. I will instead provide code closer to the real use case below. Our app has a provider which exposes a stream from an event channel, basically just In the code below I have replaced the EventChannel object with a simple When toggling between the two views I expect to see both The goal is to make the import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// This is simplified code (to not have to implement Java code).
final eventChannelStreamController = StreamController<int>();
final eventChannelStream = eventChannelStreamController.stream;
// More similar to real code:
// const eventChannel = EventChannel('event_channel');
// final eventChannelStream = eventChannel.receiveBroadcastStream();
final streamProvider = StreamProvider.autoDispose<int>((ref) {
ref.onDispose(() {
// Should something be done here?
});
return eventChannelStream.asBroadcastStream();
});
void main() {
eventChannelStreamController.onListen = () {
print('Event: onListen');
};
eventChannelStreamController.onCancel = () {
print('Event: onCancel');
};
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
bool showTestWidget = true;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body:
showTestWidget ? const TestWidget() : const Text('Another widget'),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => showTestWidget = !showTestWidget),
child: Icon(showTestWidget ? Icons.visibility_off : Icons.visibility),
),
),
);
}
}
class TestWidget extends ConsumerWidget {
const TestWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return ref.watch(streamProvider).when(
data: (value) => const Text('TestWidget got data'),
loading: () => const Text('TestWidget loading'),
error: (error, stack) => Container());
}
} |
Describe the bug
When a widget that watches a stream provider gets disposed, it should unsubscribe to the stream returned by the stream provider. This is not the case.
Real problem: I need to dispose of some resources related to a stream controller when there are no longer any listeners to its stream. But even though the widget watching the stream provider has been disposed, the
onCancel
method on the stream controller does not get called. This prevents me from disposing the resources.To Reproduce
Here is a test showing that even though the
TestWidget
is disposed, the stream returned from the stream provider still has listeners and that theonCancel
method does not get called.Expected behavior
There should be no listeners to the stream after the widget has been disposed.
The text was updated successfully, but these errors were encountered: