Reputation: 2358
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?
Upvotes: 11
Views: 5363
Reputation: 1
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreference {
static SharedPreferences? prefs;
static String token = 'token';
static String dataListKey = 'dataListKey';
static Future<void> addData(Map<String, String> data) async {
prefs = await SharedPreferences.getInstance();
List<String> dataList = prefs?.getStringList(dataListKey) ?? [];
dataList.add(jsonEncode(data));
await prefs!.setStringList(dataListKey, dataList);
}
static Future<List<Map<String, String>>> getDataList() async {
prefs = await SharedPreferences.getInstance();
List<String> dataList = prefs?.getStringList(dataListKey) ?? [];
return dataList
.map((data) => Map<String, String>.from(jsonDecode(data)))
.toList();
}
static Future<void> clearDataList() async {
prefs = await SharedPreferences.getInstance();
await prefs!.remove(dataListKey);
}
static addStringToSF(String key, String value) async {
prefs = await SharedPreferences.getInstance();
prefs!.setString(key, value);
}
static addIntToSF(String key, int value) async {
prefs = await SharedPreferences.getInstance();
prefs!.setInt(key, value);
}
static addBoolToSF(String key, bool value) async {
prefs = await SharedPreferences.getInstance();
prefs!.setBool(key, value);
}
static Future<String> getStringValuesSF(String key) async {
prefs = await SharedPreferences.getInstance();
String? getString = prefs!.getString(key);
return (getString != null) ? getString : '';
}
static Future<int> getIntValuesSF(String key) async {
prefs = await SharedPreferences.getInstance();
int? getString = prefs!.getInt(key);
return (getString != null) ? getString : 0;
}
static Future<bool> getBoolValuesSF(String key) async {
prefs = await SharedPreferences.getInstance();
bool? getbool = prefs!.getBool(key);
return (getbool != null) ? getbool : false;
}
static Future<bool> removeValues(String key) async {
prefs = await SharedPreferences.getInstance();
return await prefs!.remove(key);
}
static dynamic containsKey(String key) async {
prefs = await SharedPreferences.getInstance();
return prefs!.get(key);
}
static Future<bool> removePrefs() async {
prefs = await SharedPreferences.getInstance();
return await prefs!.clear();
}
}
SharedPreference.addStringToSF(
SharedPreference.token, logindata11.token.toString());
class Constant {
static String token = '';
}
Constant.token =
await SharedPreference.getStringValuesSF(SharedPreference.token);
Upvotes: 0
Reputation: 602
To create Singleton class of SharedPreference
:
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);
}
}
void main() async {
// Required for async calls in `main`
WidgetsFlutterBinding.ensureInitialized();
// Initialize PreferenceUtils instance.
await PreferenceUtils.init();
runApp(MyApp());
}
PreferenceUtils.setString(AppConstants.USER_ID, "");
String userId = PreferenceUtils.getString(AppConstants.USER_ID);
more: https://dev.to/lucianojung/flutter-singelton-pattern-1a38
Upvotes: 10
Reputation: 411
Use a simple Service Locator for Dart get_it. You will have many such cases when you have to have a global object to work with other than SharedPreferences too. The first step is to add dependencies for get_it. Just go to a link, and flollow steps below to set shared preferences below up.
Your SharedPreferences will be
import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SharedPrefs extends ChangeNotifier {
SharedPreferences? _prefsInstance;
SharedPrefs() {
_init();
}
Future<void> _init() async {
_prefsInstance = await SharedPreferences.getInstance();
getIt.signalReady(this);
}
bool getBool(String key, [bool elseValue = false]) {
return _prefsInstance?.getBool(key) ?? elseValue;
}
Future<bool> setBool(String key, bool value) async {
return _prefsInstance?.setBool(key, value) ?? Future.value(false);
}
}
In main.dart
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:yourpackage/shared_prefs.dart';
import 'app.dart';
GetIt getIt = GetIt.instance;
void main() {
WidgetsFlutterBinding.ensureInitialized();
getIt.registerSingleton(SharedPrefs(), signalsReady: true);
runApp(const App());
}
Anywhere you need shared preferences you call it
final authenticated = getIt<SharedPrefs>().getBool('key_auth');
Upvotes: 0
Reputation: 10319
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;
}
Upvotes: 2
Reputation: 17724
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.
Upvotes: 0