Home > Software design >  How to create a single instance of shared preferences which can be used in full project in flutter
How to create a single instance of shared preferences which can be used in full project in flutter

Time:07-20

Whenever we have to use shared preferences we have to create an instance of it.

In flutter creating an instance of shared preference is asynchronous;

final prefs = await SharedPreferences.getInstance();

we have to create its instance always whenever we have to use it like above.

Is there a way to create a single instance of shared preferences which will be available to the overall project and we don't have to create its instance again and again in Flutter?

CodePudding user response:

To create Singleton class of SharedPreference:

Put this class in 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);
         }
       }
Initialize this class in initState() main class
 void main() async {
  // Required for async calls in `main`
  WidgetsFlutterBinding.ensureInitialized();

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

  runApp(MyApp());
}
Access in methods
PreferenceUtils.setString(AppConstants.USER_ID, "");
String userId = PreferenceUtils.getString(AppConstants.USER_ID);

more: https://dev.to/lucianojung/flutter-singelton-pattern-1a38

CodePudding user response:

Apart from creating a singleton separately you can also do this.. You can create a dart file with methods defined globally. By globally i mean outside the class.

late SharedPreferences prefs;
void initiateSharedPreferences()
{
   prefs = await SharedPreferences.getInstance();
}

From main.dart call this method to initiate prefs. Now the var pref is globally available. Now wherever you use prefs you only have to import this dart file and you can use prefs normally.

CodePudding user response:

SharedPreferences.getInstance() returns already a Singleton. It reads once from disk and subsequent calls just return the resolved future. This way, just store the object returned by the await SharedPreferences.getInstance(); somewhere accessible globally.

Check out its source code below. It creates the static _completer once for the lifetime of the app.

  /// Loads and parses the [SharedPreferences] for this app from disk.
  ///
  /// Because this is reading from disk, it shouldn't be awaited in
  /// performance-sensitive blocks.
  static Future<SharedPreferences> getInstance() async {
    if (_completer == null) {
      final Completer<SharedPreferences> completer = Completer<SharedPreferences>();
      try {
        final Map<String, Object> preferencesMap = await _getSharedPreferencesMap();
        completer.complete(SharedPreferences._(preferencesMap));
      } on Exception catch (e) {
        // If there's an error, explicitly return the future with an error.
        // then set the completer to null so we can retry.
        completer.completeError(e);
        final Future<SharedPreferences> sharedPrefsFuture = completer.future;
        _completer = null;
        return sharedPrefsFuture;
      }
      _completer = completer;
    }
    return _completer!.future;
  }
  • Related