rrousselGit / riverpod

A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
https://riverpod.dev
MIT License
6.28k stars 955 forks source link

Can a provider know that it is being refreshed? #464

Closed kmod-midori closed 3 years ago

kmod-midori commented 3 years ago

Is your feature request related to a problem? Please describe. After being confused about how to implement a gaplessPlayback feature with purely providers (without hooks as they are local to a widget), I came up with this thing:

import 'package:hooks_riverpod/hooks_riverpod.dart';

class CachedAsyncValue<T> {
  final T? lastValue;
  final Object? currentError;

  CachedAsyncValue({this.lastValue, this.currentError});
}

ProviderListenable<CachedAsyncValue<T>> gaplessFutureProvider<T>(
    Future<T> Function(ProviderReference) create) {
  final ft = FutureProvider<T>(create);
  T? cached;

  return Provider((ref) {
    return ref.watch(ft).when(
        data: (data) {
          cached = data;
          return CachedAsyncValue(lastValue: cached);
        },
        loading: () => CachedAsyncValue(lastValue: cached),
        error: (e, s) => CachedAsyncValue(lastValue: cached, currentError: e));
  });
}

However, I was unable to refresh this provider's data properly with context.refresh(someGaplessProvider) as the internal FutureProvider is never refreshed. It is possible to refresh the internal provider thanks to #335, but being unable to distinguish between rebuilds and refreshes prevents me from implementing this as there will be an infinite loop if I unconditionally call ref.refresh here.

Describe the solution you'd like Something like ref.isRefreshing, or a way to indicate that that provider A is "tightly related" to provider B so that refreshing A also refreshes B.

Describe alternatives you've considered Some complex Rx code that does this.

Additional context The hooks approach in #333 works fine, but is not feasible in my application because I need my provider to be compatible with context.read().

rrousselGit commented 3 years ago

I would prefer implementing directly in Riverpod a gapless functionality rather than expose such a flag.

In fact, this is very much planned and is one of the motivations behind #335

rrousselGit commented 3 years ago

Closing since I do not intend on adding such feature