riverpod
riverpod copied to clipboard
Implement cacheTime/staleTime
It has been decided to remove cacheTime
as part of the initial release, as the initial implementation had some issues.
This issue is for tracking the re-introduction of cacheTime
, accompagned by staleTime
.
staleTime
would be the amount of time before the value is considered obsolete. At this point, the provider should re-execute when given the opportunity.
But the value exposed wouldn't be destroyed immediately.
Instead the value will be available for caheTime
after stateTime
as expired.
For reference, even if these APIs won't be part of the initial 2.0 release:
- they will be added in the future
- you can implement
cacheTime
yourself usingref.keepAlive()
+ aTimer()
TL;DR about implementing cacheTime
on your own:
extension on AutoDisposeRef {
// When invoked keeps your provider alive for [duration]
void cacheFor(Duration duration) {
final link = keepAlive();
final timer = Timer(duration, () => link.close());
ref.onDispose(() => timer.cancel());
}
}
final myProvider = Provider.autoDispose<int>((ref) {
ref.cacheFor(Duration(minutes: 5));
});
@rrousselGit I have two questions about this implementation.
Question 1. By looking at cacheTime
and disposeDelay
, I read, respectively:
The minimum amount of time before an
autoDispose
provider can be disposed if not listened.
and
The amount of time before a provider is disposed after its last listener is removed.
I feel like the implementation above is closer to disposeDelay
than it is to cacheTime
(which is actually what I need in my use case, so that's cool). Am I getting this right?
Question 2. If keepAlive
works the same as maintainState
, how will the dispose
event ever trigger - we are telling this provider not to dispose, right? This would mean that the callback inside onDispose
will never trigger, right?
I feel like the implementation above is closer to disposeDelay than it is to cacheTime (which is actually what I need in my use case, so that's cool). Am I getting this right?
No 😋
What I implemented is indeed cacheTime. When it was available in the dev release, that's quite litteraly how it worked.
The onDispose is for when using ref.watch/invalidate/... A provider can get disposed even if it's listened when using those.
Re-reading the definitions and the implementation I totally see that it's cacheTime
being implemented there. Thank you @rrousselGit.
For reference for other users, I tried to implement disposeDelay
, too! This seems to be working, but I'd like to have your "blessings" 😛 Let me know.
extension TestExtension<T> on AutoDisposeRef<T> {
void disposeDelay(Duration duration) {
final link = keepAlive();
Timer? timer;
onCancel(() {
timer?.cancel();
timer = Timer(duration, link.close);
});
onDispose(() {
timer?.cancel();
});
onResume(() {
timer?.cancel();
});
}
void cacheFor(Duration duration) {
final link = keepAlive();
final timer = Timer(duration, link.close);
onDispose(timer.cancel);
}
}
EDIT. implemented remi's suggestions.
You'll want to restart the timer too on onResume
.
But let's be clear: disposeDelay
isn't going to be added back
You'll want to restart the timer too on
onResume
.
True. Thanks!
But let's be clear:
disposeDelay
isn't going to be added back
Why is that?
I think extra functionalities shouldn't be included in the base package. All we need is flexibility and stability.
We wanted cacheTime
and disposeDelay
because before that, working with combination of Timer
and ref.maintainState
was buggy. Now I see KeepAliveLink
works flawlessly. It's just few lines of code as implementation and again, 1 line of code in each provider.
@rrousselGit sorry to bother you, but would the following be a fair implementation of staleTime
?
void staleTime(Duration duration) {
var timer = Timer(duration, invalidateSelf);
onAddListener((){
timer.cancel();
timer = Timer(duration, invalidateSelf);
});
onDispose((){
timer.cancel();
});
}
Possibly
Although both cacheTime and staleTime would be part of Riverpod itself, to simplify combining them with error handling and async (cacheTime/staleTime should start when a FutureProvider completes and even after an error)
Also, cacheTime must start after staleTime. So there's a bit of logic needed here