Search code examples
flutterdartsharedpreferences

Flutter: How to use SharedPreferences synchronously?


I am using Shared Preferences in my Flutter app and what I would like to do is store SharedPreferences as a field on startup and then use it synchronously in the app. However I'm not sure if I'm not missing anything. What I want to achieve is instead of:

method1() async {
  SharedPreferences sp = await SharedPreferences.getInstance();
  return sp.getString('someKey');
}

to

SharedPreferences sp;
//I would probably pass SharedPreferences in constructor, but the idea is the same
someInitMethod() async {
  sp = await SharedPreferences.getInstance();
}
method1() {
  return sp.getString('someKey');
}
method2() {
  return sp.getString('someKey2');
}
method3() {
  return sp.getString('someKey3');
}

In that way I would achieve synchronous access to sharedPrefs. Is it bad solution?

EDIT:
What is worth mentioning is that getInstance method will only check for instance and if there is any than it returns it, so as I see it, is that async is only needed to initialize instance. And both set and get methods are sync anyway.

static Future<SharedPreferences> getInstance() async {
  if (_instance == null) {
    final Map<String, Object> fromSystem =
        await _kChannel.invokeMethod('getAll');
    assert(fromSystem != null);
    // Strip the flutter. prefix from the returned preferences.
    final Map<String, Object> preferencesMap = <String, Object>{};
    for (String key in fromSystem.keys) {
      assert(key.startsWith(_prefix));
      preferencesMap[key.substring(_prefix.length)] = fromSystem[key];
    }
    _instance = new SharedPreferences._(preferencesMap);
  }
  return _instance;
}

Solution

  • I use the same approach as the original poster suggests i.e. I have a global variable (actually a static field in a class that I use for all such variables) which I initialise to the shared preferences something like this:

    in globals.dart:

    class App {      
      static SharedPreferences localStorage;
      static Future init() async {
        localStorage = await SharedPreferences.getInstance();
      }
    }
    

    in main.dart:

    void main() {
      start();
    }
    
    Async.Future start() async {
      await App.init();
      localStorage.set('userName','Bob');
      print('User name is: ${localStorage.get('userName)'}');  //prints 'Bob'
    }
    

    The above worked fine but I found that if I tried to use App.localStorage from another dart file e.g. settings.dart it would not work because App.localStorage was null but I could not understand how it had become null.

    Turns out the problem was that the import statement in settings.dart was import 'package:<packagename>/src/globals.dart'; when it should have been import 'globals.dart;.