Reputation: 2375
I want to store an object in shared preferences which contains some fields in it like name, age, phone number etc. I don't know how to store an object in shared preferences in flutter.
Upvotes: 52
Views: 71147
Reputation: 338
You can use Freezed package for serialized object and then:
Save data on preference:
SharedPreferences pref = await SharedPreferences.getInstance();
await prefs.setString('playerData', jsonEncode(playerData.toJson()));
Get data from preference
SharedPreferences pref = await SharedPreferences.getInstance();
final jsonString = prefs.getString('playerData');
PlayerData pd = PlayerData.fromJson(jsonDecode(jsonString));
Upvotes: 2
Reputation: 1873
After searching a lot of articles here you are
For saving data to SharedPreferences instance, object must be converted to JSON:
SharedPreferences prefs = await SharedPreferences.getInstance();
Map<String, dynamic> user = {'Username':'tom','Password':'pass@123'};
bool result = await prefs.setString('user', jsonEncode(user));
For getting data from SharedPreferences instance, object must converted from JSON:
String userPref = prefs.getString('user');
Map<String,dynamic> userMap = jsonDecode(userPref) as Map<String, dynamic>;
shared_preferences need to be installed: https://pub.dev/packages/shared_preferences/install
Upvotes: 52
Reputation: 563
Paste this anywhere in your codebase (please, try to be organized!)
/// e.g: my_custom_extensions.dart
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
extension JsonMethods on SharedPreferences {
Future<bool> setJson(String key, Map<String, dynamic> json) async {
bool result = await setString(key, jsonEncode(json));
return result;
}
Map<String, dynamic>? getJson(String key) {
String? storedJson = getString(key);
if (storedJson == null) return null;
Map<String, dynamic> parsedStoredJson = jsonDecode(storedJson) as Map<String, dynamic>;
return parsedStoredJson;
}
}
Although I believe some of the answers here actually help answer the question being asked, I think the best (and cleanest) way to do it would be with an extension method. (You can read more about them here).
Basically what we're doing, is that we're making the "SharedPreferences" class have two new methods (setJson & getJson).
This methods can essentially do whatever we want, but also is very important to note that we have access to the instance of "SharedPreferences". (Remember, an instance is an instantiated class).
Example:
final mySuperAwesomeInstance = SharedPreferences();
Now, instead of having an explicit SharedPreferences instance (as in the line above), we have an implicit one (which we can access with the "this" keyword.
Example:
extension JsonMethods on SharedPreferences {
Future<bool> setJson(String key, Map<String, dynamic> json) async {
bool result = await this.setString(key, jsonEncode(json)); /// <- Note the "this.setString()"
return result;
}
}
But because Dart is so amazingly awesome, we can just access the method without the "this" keyword :).
extension JsonMethods on SharedPreferences {
Future<bool> setJson(String key, Map<String, dynamic> json) async {
bool result = await setString(key, jsonEncode(json)); /// <- Here!
return result;
}
}
NOTE: Extension methods can have any names we want, in this case I chose setJson & getJson to follow the SharedPreferences naming convention. But you can pick any names you like for your methods.
Upvotes: -1
Reputation: 7128
I have created a LocalStorageRepository
class, that is responsible to handle local data using SharedPreferences
.
The class is dynamic and can work with any type of data (int, double, bool, String, and Object) using generics and JSON decoding and encoding.
In order to prevent pron errors, I added the LocalStorageKeys
enum to handle the supported keys. Feel free to add more keys to that enum.
enum LocalStorageKeys { tutorialCompleted, user }
@singleton
class LocalStorageRepository {
const LocalStorageRepository(SharedPreferences prefs) : _prefs = prefs;
final SharedPreferences _prefs;
bool keyExists(String key) => _prefs.containsKey(key);
T? getValue<T>(
LocalStorageKeys key, [
T Function(Map<String, dynamic>)? fromJson,
]) {
switch (T) {
case int:
return _prefs.getInt(key.name) as T?;
case double:
return _prefs.getDouble(key.name) as T?;
case String:
return _prefs.getString(key.name) as T?;
case bool:
return _prefs.getBool(key.name) as T?;
default:
assert(fromJson != null, 'fromJson must be provided for Object values');
if (fromJson != null) {
final stringObject = _prefs.getString(key.name);
if (stringObject == null) return null;
final jsonObject = jsonDecode(stringObject) as Map<String, dynamic>;
return fromJson(jsonObject);
}
}
return null;
}
void setValue<T>(LocalStorageKeys key, T value) {
switch (T) {
case int:
_prefs.setInt(key.name, value as int);
break;
case double:
_prefs.setDouble(key.name, value as double);
break;
case String:
_prefs.setString(key.name, value as String);
break;
case bool:
_prefs.setBool(key.name, value as bool);
break;
default:
assert(
value is Map<String, dynamic>,
'value must be int, double, String, bool or Map<String, dynamic>',
);
final stringObject = jsonEncode(value);
_prefs.setString(key.name, stringObject);
}
}
}
In case you want to get an Object value from LocalStorageRepository
, you will need to provide its fromJson
decoder.
final user = _localStorage.getValue(LocalStorageKeys.user, User.fromJson);
Hope that hence example will help others out there.
Feel free to edit this question and suggest any changes.
Upvotes: 3
Reputation: 1026
SharedPreferences shared_User = await SharedPreferences.getInstance();
Map decode_options = jsonDecode(jsonString);
String user = jsonEncode(User.fromJson(decode_options));
shared_User.setString('user', user);
SharedPreferences shared_User = await SharedPreferences.getInstance();
Map userMap = jsonDecode(shared_User.getString('user'));
var user = User.fromJson(userMap);
class User {
final String name;
final String age;
User({this.name, this.age});
factory User.fromJson(Map<String, dynamic> parsedJson) {
return new User(
name: parsedJson['name'] ?? "",
age: parsedJson['age'] ?? "");
}
Map<String, dynamic> toJson() {
return {
"name": this.name,
"age": this.age
};
}
}
Upvotes: 50
Reputation: 1109
If you are getting you data from an API, what you initially get from an API endpoint is a String so you can store the data as a raw String and when you need it you can deserialize it and use where you want to use it
https://gist.github.com/k1ycee/33bb7e51dac81093f949bbd30d7d0dc9
Something like this, the drawback I feel is that if the JSON string data is much might not be advisable to store all the string rather deserialize it and take the ones you deem necessary.
Upvotes: 0
Reputation: 10975
To Save the object to Shared Preferences
SharedPreferences pref = await SharedPreferences.getInstance();
Map json = jsonDecode(jsonString);
String user = jsonEncode(UserModel.fromJson(json));
pref.setString('userData', user);
To Fetch the object from Shared Preferences
SharedPreferences pref = await SharedPreferences.getInstance();
Map json = jsonDecode(pref.getString('userData'));
var user = UserModel.fromJson(json);
You will need to import below mentioned packages
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
Easiest way to create Model Follow this answer -> https://stackoverflow.com/a/58708634/9236994
Upvotes: 18
Reputation: 3174
When Getting Data from the API and Saving it Into Sharepreference
Future<UserDetails> UserInfo({String sesscode, regno}) async{
await Future.delayed(Duration(seconds: 1));
SharedPreferences preferences = await SharedPreferences.getInstance();
var map = new Map<String, String>();
map["sesscode"] = sesscode;
map["regno"] = regno;
var response = await http.post(Base_URL().user_info, body: map);
Map decodedata = json.decode(response.body);
if(decodedata != null){
String user = jsonEncode(UserDetails.fromJson(decodedata));
preferences.setString(SharePrefName.infoPref, user);
return UserDetails.fromJson(decodedata);
}
return null;
}
I Create A function for Getting the Details You can call this function anywhere in your App
Future<UserDetails> getSavedInfo()async{
SharedPreferences preferences = await SharedPreferences.getInstance();
Map userMap = jsonDecode(preferences.getString(SharePrefName.infoPref));
UserDetails user = UserDetails.fromJson(userMap);
return user;
}
Now, Am calling it inside a Class to get username
Future<UserDetails> usd = getSavedInfo();
usd.then((value){
print(value.surname);
});
Upvotes: 3
Reputation: 657288
You need to serialize it to JSON before saving and deserialize after reading
See https://flutter.io/docs/development/data-and-backend/json for details
Upvotes: 13