-
-
Notifications
You must be signed in to change notification settings - Fork 908
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
Future provider memory leak #3522
Comments
All of that sounds normal to me.
|
I guess I just expected both I find it weird that an unused auto-dispose provider leaves a listener attached to its dependency forever. This fundamentally causes a memory leak because if you:
In the end, you'll only have one Why doesn't the watch method in |
Oh, I think I got confused about the issue. I'll investigate. Sounds like a bug for sure. Thanks for the report. |
My project relies on this task being fixed urgently. If I were to make a PR and it's merged successfully, could it be a part of a minor release, or would it have to wait until 3.0? |
It depends on the changes involved. But if it has to be a 3.0.0 fix, you could always stick to using your fork in the meantime |
I'm not exactly sure how to fix this. If provider |
@rrousselGit I managed to fix it by simply checking the |
I've got the same bug (which was hard to catch). A temporary solution is to update aProvider to watch the future before the await: @riverpod
Future<int> a(ARef ref) async {
print('buildA');
ref.onAddListener(() {
print('addA');
});
ref.onRemoveListener(() {
print('removeA');
});
ref.onCancel(() {
print('cancelA');
});
final bFuture = ref.watch(bProvider.future);
await Future.delayed(const Duration(seconds: 5));
await bFuture;
return 5;
} |
@AhmedLSayed9 that kinda works but you would end up making that network call even if provider is disposed and there's no need. also it gets quite messy the more futures you have in your provider. @riverpod
Future<int> a(ARef ref) async {
print('buildA');
ref.onAddListener(() {
print('addA');
});
ref.onRemoveListener(() {
print('removeA');
});
ref.onCancel(() {
print('cancelA');
});
final keepAliveLink = ref.keepAlive(); // make it non disposable
await Future.delayed(const Duration(seconds: 5));
await ref.watch(bProvider.future);
keepAliveLink.close(); // release
return 5;
} |
This would occur in both cases. I'd use
The |
Yup that's why I said if you ok with that. Some requests unfortunately can't be canceled e.g supabase db calls, etc
Fair enough. You'd want to have a wrapper function that would handle with try/catch/finally which gets quite ugly regardless. The proper solution is to just throw when trying to use watch/listen of disposed refs which is coming in v3. For now we may just have to stick to a fork |
Describe the bug
Listeners are added when they shouldn't be when using future providers. This leads to a memory leak since the listeners are never removed.
Dependencies
Code
If you display
SomeScreen
, then click back within 5 seconds (the delay inaProvider
), the following is printed:A listener for
bProvider
is added but never removed even though nothing is listening toaProvider
anymore. Shouldn'taProvider
check its own aliveness before adding a listener tobProvider
on the lineref.watch(bProvider.future)
?Expected behavior
The listener on
bProvider
should never be addedThe text was updated successfully, but these errors were encountered: