Flutter Riverpod - Initialize with async values

2,331

Yes, it is possible as Abion47's comment. Let me show more details in the code below

class EmailNotifier extends ChangeNotifier {
  String email = '';

  void load() {
    functionReturnFuture.then(value) {
      setEmail(value);
    }
  }

  void setEmail(String value) {
    // email loaded but not changed, so no need to notify the listeners
    if(value == email) return;

    // email has loaded and change then we notify listeners
    email = value;
    notifyListeners();
  }
}


var emailNotifier = ChangeNotifierProvider<EmailNotifier>((ref) {
  var notifier = EmailNotifier();

  // load the email asynchronously, once it is loaded then the EmailNotifier will trigger the UI update with notifyListeners
  notifier.load();
  return notifier;
});

As we manage state independently from Flutter UI, there is nothing blocking you from running code to trigger a state change, for example in our case notifier.load().

After notifier.load() and email is set then the provider will trigger UI change using notifyListeners().

You can achieve a similar result using FutureProvider.

Share:
2,331
swedishcheef
Author by

swedishcheef

Updated on December 24, 2022

Comments

  • swedishcheef
    swedishcheef 12 months

    I'm trying to learn Riverpod and I have a ChangeNotifierProvider that has a few fields that need to be initialized with a value that is returned from an async operation. Is this possible, as I know I cant create the ChangeNotifierProvider asynchronously?

    Example ChangeNotifierProvider

    class SomeState extends ChangeNotifier {
      String email = '';
    
      // needs to be set to value returned from
      // shared preferences upon init
    }
    

    If not possible, is there another provider that could work better knowing I want to initialize its value to the returned value from async method?

    • Abion47
      Abion47 about 3 years
      Forcing the state to wait for the returned value of a future can stall the whole app. Instead, call the async method within the initialization of your state and, when it is complete, save the value and call notifyListeners() to rebuild any listening widgets.
    • swedishcheef
      swedishcheef about 3 years
      Thanks @Abion47, that makes sense. Going to try to refactor.
    • Rémi Rousselet
      Rémi Rousselet about 3 years
      You can add a "bool isLoading" flag
    • swedishcheef
      swedishcheef about 3 years
      Thanks @RémiRousselet, not sure I follow where I should put this flag though?
    • Rémi Rousselet
      Rémi Rousselet about 3 years
      Inside your SomeState class
    • swedishcheef
      swedishcheef about 3 years
      something like class SomeState extends ChangeNotifier { String email = ''; bool isLoading = false; void init() async { isLoading = true; var res = await method(); email = res.email; isLoading = false; notifylListeners(); } } ??