shalini
shalini

Reputation: 2375

Store data as an object in shared preferences in flutter

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

Answers (9)

Luca Biasotto
Luca Biasotto

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

Omar Essam El-Din
Omar Essam El-Din

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

Miguel Jara
Miguel Jara

Reputation: 563

TL;DR - Extension Methods

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;
  }
}

Long, boring explanation (a recommended read)

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

genericUser
genericUser

Reputation: 7128

SharePreferences Handler

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

Bhoomika Chauhan
Bhoomika Chauhan

Reputation: 1026

You can Store an object in shared preferences as Below:

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

Denzel
Denzel

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

Vicky Salunkhe
Vicky Salunkhe

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

SilenceCodder
SilenceCodder

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

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

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

Related Questions