How to create Singleton class of SharedPreferences in flutter

Viewed 8161

Always required object of SharedPreferences but we access using await Like.

await SharedPreferences.getInstance();

That's why I thought create Singleton class of SharedPreferences and create static method for GET & SET data in SharedPreferences.

But I dont know how to do this, I try but cant get success
Please Help me

5 Answers

For handle singleton class SharedPreference follow there 3 steps -

1. Put this class in your project

    import 'dart:async' show Future;
    import 'package:shared_preferences/shared_preferences.dart';

    class PreferenceUtils {
      static Future<SharedPreferences> get _instance async => _prefsInstance ??= await SharedPreferences.getInstance();
      static SharedPreferences _prefsInstance;

      // call this method from iniState() function of mainApp().
      static Future<SharedPreferences> init() async {
        _prefsInstance = await _instance;
        return _prefsInstance;
      }

      static String getString(String key, [String defValue]) {
        return _prefsInstance.getString(key) ?? defValue ?? "";
      }

      static Future<bool> setString(String key, String value) async {
        var prefs = await _instance;
        return prefs?.setString(key, value) ?? Future.value(false);
      }
    }


2. Initialize this class from your initState() of main class

PreferenceUtils.init();

3. Access your methods like

PreferenceUtils.setString(AppConstants.USER_NAME, "");
String username = PreferenceUtils.getString(AppConstants.USER_NAME);

You can use following very simple class to get the SharedPreferences instance without await:

import 'package:shared_preferences/shared_preferences.dart';

class SharedPrefs {
  static late final SharedPreferences instance;

  static Future<SharedPreferences> init() async =>
      instance = await SharedPreferences.getInstance();
}
  1. Initiliaze the instance maybe in main() function, as follows:
void main() async {
  // Required for async calls in `main`
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize SharedPrefs instance.
  await SharedPrefs.init();

  runApp(MyApp());
}
  1. Access methods on SharedPrefs.instance, for e.g.:
final someString = SharedPrefs.instance.getString('someString') ?? 'defaultValue';
await SharedPrefs.instance.setBool('someBool', true);

Extra:
If preferred, one can further abstract by redefining these methods (getBool, setString, etc.) or defining new methods (getUser, setUser, setAccessToken etc.) in SharedPrefs class itself and making instance a private field like _instance.

One such example is as follows:

// Getter
static bool? getBool(String key) => _instance.getBool(key);

// Setter
static Future<bool> setBool(String key, bool value) => _instance.setBool(key, value);

// More abstraction
static const _kAccessToken = 'accessToken';

static Future<bool> setAccessToken(String value) => _instance.setString(_kAccessToken, value);

static String? getAccessToken() => _instance.getString(_kAccessToken);

After this, one can simply call these methods, as follows:

final someBool = SharedPrefs.getBool('someBool') ?? false;
await SharedPrefs.setBool('someBool', someBool);

final accessToken = SharedPrefs.getAccessToken();

Here is my solution for prefs:

class Storage {
  static const String _some_field = 'some_field';

  static Future<SharedPreferences> get prefs => SharedPreferences.getInstance();

  static Future<String> getSomeStringData() async =>
      (await prefs).getString(_some_field) ?? '';

  static Future setSomeStringData(String phone) async =>
      (await prefs).setString(_some_field, phone);

  static Future clear() async {
    await getSomeStringData(null);
  }
}

I use this code for a singleton preference

static Future<SharedPreferences>  getInstance() async
  {
    SharedPreferences preferences ;
    preferences = await SharedPreferences.getInstance();
    return preferences;
  }

And then Use it like that to restore your data , Here I restore userId.

 /// ----------------------------------------------------------
  /// Method that saves/restores the userId
  /// ----------------------------------------------------------
   static Future<String>  getUserId() async {
    return getInstance().then((pref) {
      return pref.get(Constants.userId);
    });
  }

Hope it helps :)

class YourClass {
    static final YourClass _singleton = 
           new YourClass._internal();

    factory YourClass(){
            return _singleton;
    }
    
    YourClass._internal(){
            //initialization your logic here
    }

}

//main code env
//get back the singleton to you
YourClass mClass = new YourClass(); 
Related