Flutter: shared preferences
Asked Answered
A

2

15

I have this function:

  Future<String> load(SharedPreferences prefs, String fileName) async {
    prefs = await SharedPreferences.getInstance();
    String jsonString = prefs.getString(fileName) ?? "";
    if (jsonString.isNotEmpty) {
      return jsonString;
    }else{
      return ...
    }
  }

What should I return in the else case? I tried with "" but it doesn't work.

Antonetta answered 16/10, 2018 at 8:55 Comment(7)
What does "doesn't work" mean exactly?Priscilapriscilla
String jsonString = prefs.getString(fileName) ?? ""; - is wrong, You have to do String jsonString = (await prefs.getString(fileName)) ?? "";Hushhush
because, when I try to load, It gives me "FormatException: Unexpected end of input (at character 1)Antonetta
If i put that await there, it will complain telling me "await only futures"Antonetta
should I just put in the load an if condition like (!= "") ?Antonetta
You are right about await I've just looked into different realization of prefs. It seems totally fine. Is problem exactly in else block?Hushhush
I could solve easily writing an if condition (data != "") when I load this file, but was just curiosity if there was another wayAntonetta
S
9

The answer is "it depends". Namely, it depends on what exactly you are doing with the result of this function, and what a good empty default value means in that context.

Assuming you're decoding the returned JSON string into a Map<String, dynamic>, then a good default value might be the empty map. In that case, you could reformulate your function as follows:

Future<String> loadJSON(final String fileName) async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  final String jsonString = prefs.getString(fileName);
  if (jsonString != null && jsonString.isNotEmpty) {
    return jsonString;
  }
  return "{}"; // default value
}

final String jsonString = await loadJSON("test.json");

final Map<String, dynamic> jsonData = json.decode(jsonString);

However, it probably makes more sense to reformulate this procedure as a slightly higher-level function returning actual map values:

Future<Map<String, dynamic>> loadData(final String fileName) async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  final String jsonString = prefs.getString(fileName);
  if (jsonString != null && jsonString.isNotEmpty) {
    return json.decode(jsonString);
  }
  return Map(); // default value
}

final Map<String, dynamic> jsonData = await loadData("test.json");
Shaitan answered 2/11, 2018 at 8:51 Comment(0)
C
36

Shared Preferences

In Flutter, Shared Preferences are used to store primitive data (int, double, bool, string, and stringList). This data is associated with the app, so when the user uninstalls your app, the data will also be deleted.

Get the plugin

The shared_preferences plugin from pub is a wrapper around Android SharedPreferences and iOS NSUserDefaults. You can get this plugin by adding the shared_preferences line to your pubspec.yaml file in the dependencies section.

dependencies:
  shared_preferences: '>=0.5.12+2 <2.0.0'

You can change the version number to whatever the current one is, but anything less than 2.0 should be compatible.

Import the package

In whichever file you need the Shared Preferences, add the following import:

import 'package:shared_preferences/shared_preferences.dart';

Reading and writing data

To get the shared preferences object you can do the following:

final prefs = await SharedPreferences.getInstance();

This will be used for all of the following examples.

int

  • read: final myInt = prefs.getInt('my_int_key') ?? 0;
  • write: prefs.setInt('my_int_key', 42);

double

  • read: final myDouble = prefs.getDouble('my_double_key') ?? 0.0;
  • write: prefs.setDouble('my_double_key', 3.14);

bool

  • read: final myBool = prefs.getBool('my_bool_key') ?? false;
  • write: prefs.setBool('my_bool_key', true);

string

  • read: final myString = prefs.getString('my_string_key') ?? '';
  • write: prefs.setString('my_string_key', 'hello');

stringList

  • read: final myStringList = prefs.getStringList('my_string_list_key') ?? [];
  • write: prefs.setStringList('my_string_list_key', ['horse', 'cow', 'sheep']);

Removing data

You can remove any saved data by supplying the key name:

prefs.remove('my_int_key');

I rarely find a need to do that, though. I just overwrite the old data or ignore it. You shouldn't store any sensitive data in Shared Preferences.

See also

Carcassonne answered 4/1, 2019 at 0:54 Comment(1)
This is the most amazing way you explained Shared Preference. If only this was how the documentation explained it. Thanks a lot!Knighton
S
9

The answer is "it depends". Namely, it depends on what exactly you are doing with the result of this function, and what a good empty default value means in that context.

Assuming you're decoding the returned JSON string into a Map<String, dynamic>, then a good default value might be the empty map. In that case, you could reformulate your function as follows:

Future<String> loadJSON(final String fileName) async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  final String jsonString = prefs.getString(fileName);
  if (jsonString != null && jsonString.isNotEmpty) {
    return jsonString;
  }
  return "{}"; // default value
}

final String jsonString = await loadJSON("test.json");

final Map<String, dynamic> jsonData = json.decode(jsonString);

However, it probably makes more sense to reformulate this procedure as a slightly higher-level function returning actual map values:

Future<Map<String, dynamic>> loadData(final String fileName) async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  final String jsonString = prefs.getString(fileName);
  if (jsonString != null && jsonString.isNotEmpty) {
    return json.decode(jsonString);
  }
  return Map(); // default value
}

final Map<String, dynamic> jsonData = await loadData("test.json");
Shaitan answered 2/11, 2018 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.