Search code examples
flutterriverpodriverpod-generator

Riverpod generator and generating util classes


I'm trying to work with Riverpod, specifically with riverpod_generator and since there is not a lot of documentation surrounding this, I'm having trouble setting up a project to make use of all of this. I want to create a provider with the shared_preferences package so I can access this provider globally. It's seems by using this generator you can avoid to know which provider you need (state, future, etc.) which is neat thing I must say but I'm not quite sure I understand the whole scope yet.

First the class that will be the global shared pref provider (although this is not set up correctly, hence the ask for help)

@riverpod // annotation for the riverpod_generator
class SharePrefNotifier extends _$SharePrefNotifier{
  @override
  SharedPreferences build() {
    return _sharedPreferences;
  }

  // Obtain shared preferences but this is not correct although the compiler asks to be late
  late SharedPreferences _sharedPreferences;

  int? get getPin =>
      _sharedPreferences.getInt(_pinKey);

  Future<void> setPin(int? pinNumber) async => await _sharedPreferences.setInt(_pinKey, pinNumber);
   
  
  Future<void> removePin() async => await _sharedPreferences.remove(_pinKey);
   
  

  Future<void> deleteAll() async => await _sharedPreferences.clear();
}

When I fix the setup for shared pref provider, I want to access it in another provider:


@riverpod
class SettiingPinNotifier extends _$SettiingPinNotifier {
// referencing the shared_pred notifier on the top of the scope if possible so I can reference it anywhere in this provider if I have multiple methods
  final sharedPrefProvider = ref.read(sharedPrefProvider.notifer);
  @override
  SomeDataState build() {

    return const SomeDataState();
  }


  void setUpAPin(int? number) {
      sharedPrefProvider.setPin(number); // referencing the shared pref provider and setup a pin number
    state = state.copyWith(pin: number); // adding it to the state so I can change the UI accordingly 
  }


}

What is the best approach here BUT using the said riverpod_generator/riverpod_annotation? Thanks in advance for your help.


Solution

  • We don't have an actual instance of SharedPreferences, and we can't get one except asynchronously, thus creating the following dummy provider.

    @riverpod
    SharedPreferences sharedPreferences(ref) {
      throw UnimplementedError();
    }
    

    After that in the main.dart

    final prefs = await SharedPreferences.getInstance();
      return runApp(
        ProviderScope(
          overrides: [
            // Override the unimplemented provider with the value gotten from the plugin
            sharedPreferencesProvider.overrideWithValue(prefs),
          ],
          child: const MyApp(),
        ),
    

    );

    And finally create a service that deals with the SharedPreferences instance, and a provider for it.

    @riverpod
    SharedPreferencesService sharedPreferencesService(SharedPreferencesServiceRef ref) {
      final sharedPreferences = ref.watch(sharedPreferencesProvider);
    
      return SharedPreferencesService(sharedPreferences);
    }
    
    class SharedPreferencesService {
      SharedPreferencesService(this.sharedPreferences);
    
      final SharedPreferences sharedPreferences;
    
      Future<void> setPin(int? pinNumber) async => await sharedPreferences.setInt(_pinKey, pinNumber);
      // add all methods, getters, and etc.
    }