How to save a list to shared preferences - flutter

I want to save a list to shared preferences, but it doesn't work... The goal is to add data to the variable and save it.
This is the variable I want to save:
var savedData = [
{'date': 0, 'testNumber': 0},
];
And this is the code I tried for saving and receiving the variable:
Future<void> saveDataTest() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setStringList(
'dataTest', savedData.map((i) => i.toString()).toList());
}
Future<String> getDataStringTest() async {
final prefs = await SharedPreferences.getInstance();
savedData =
prefs.getStringList('dataTest').map((i) => int.parse(i)).toList();
setState(() {});
}
This is the error I get:
A value of type 'List<int>' can't be assigned to a variable of type 'List<Map<String, int>>'.
Try changing the type of the variable, or casting the right-hand type to 'List<Map<String, int>>'.

As you are using in your list a Map object with primitive types, you can use jsonEncode and convert to a String that can be saved in sharedPreferences and use jsonDecoder when want to revert.
like this:
String toBeSaved = jsonEncode(savedData);
prefs.setString('dataTest', toBeSaved);

Try using jsonEncode and jsonDecode from import 'dart:convert';
Like so:
Future<void> saveDataTest() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString("dataTest ", jsonEncode(savedData));
}
Future<String> getDataStringTest() async {
final prefs = await SharedPreferences.getInstance();
savedData = List.from(jsonDecode(prefs.getString("dataTest")));
setState(() {});
}

Related

Dart: A value of type 'String?' can't be assigned to a variable of type 'String'

There are 2 functions. One must return String other save this String in with SharedPreferences.
The problem is, that by using prefs.getString() I get not a String but another object.
The error called: A value of type 'String?' can't be assigned to a variable of type 'String'.
getCurrentCityFromSharedPreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('currentCity');
}
Future<void> setCurrentCityInSharedPreferences(String newCity) async{
final prefs = await SharedPreferences.getInstance();
prefs.setString('currentCity', newCity);
}
I have tried to rewrite function to
Future<String?> getCurrentCityFromSharedPreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('currentCity');
}
but then I get as string Deskription of object: Instance of 'Future<String?>'
your set string type is simply string and get type is String?
so change set type like this
Future<void> setCurrentCityInSharedPreferences(String? newCity) async{
final prefs = await SharedPreferences.getInstance();
prefs.setString('currentCity', newCity!);
}
When you try to get currentCity from SharedPreferences you get an object of type String?. This basically means that the returned object is a string that can also be null (in case there is no data stored with the key currentCity in SharedPreferences).
So, you can't do something like:
String s = prefs.getString('currentCity');
You have to handle the possibility of the value being null.
You can either declare the variable as String? like this:
String? s = prefs.getString('currentCity');
Or you can do something like:
String s = prefs.getString('currentCity') ?? "No City";
So, if you want to handle null values in the getCurrentCityFromSharedPreferences function then what you can do is:
Future<String> getCurrentCityFromSharedPreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('currentCity') ?? "No City";
}
You can replace "No City" with any value that you want to show when there is no city saved in SharedPreferences.

How to retrieve data from Future object properly?

I'm using shared preferences. I want to get the list of strings, but for some reason it's always a null though it shouldn't be. I think I'm making a mistake in asynchronous stuff. Can somebody help me? With explanation if possible.
List<String> getSaved() {
List<String>? items;
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
prefs.then((prefs) async {
items = prefs.getStringList('saved');
});
// SharedPreferences prefs = await SharedPreferences.getInstance();
// items = prefs.getStringList('saved');
return items ?? [];
}
Because you want the result when the future completed your function should be of type Future<List<String>> and you can use then or await knowing that items should be of the same type too
Future<List<String>> getSaved() async {
List<String>? items;
SharedPreferences prefs = await SharedPreferences.getInstance();
items = prefs.getStringList('saved');
// SharedPreferences prefs = await SharedPreferences.getInstance();
// items = prefs.getStringList('saved');
return items ?? [];
}

returning a String when getting error: type 'Future<dynamic>' is not a subtype of type 'String'

I can't work out how to return a string from a function in Dart (a Flutter app).
I am using SharedPreferences to capture input from the user. I have two functions, one to save preferences:
save(key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, value);
print('saved $value');
}
and one to read preferences:
read(key) async {
final prefs = await SharedPreferences.getInstance();
final value = prefs.getString(key) ?? 0;
print('$value');
}
This is working, but when I try to replace the print line with a return:
read(key) async {
final prefs = await SharedPreferences.getInstance();
final value = prefs.getString(key) ?? 0;
return('$value');
}
to return a string for the value, it throws an error:
type 'Future' is not a subtype of type 'String'
I have tried calling it many MANY different ways, but can't figure out what I assume is an incredibly basic problem. I noticed in some posts that this is a suggested solution, which works to print out the value, but I don't want to print it, i want it as a String variable:
read(mykey).then((value) => '$value');
I need to combine the value with other some other string values and make some minor manipulations (so printing it isn't helpful)
UPDATE
I have defined the function as #Stijn2210 suggested, but am still having problems getting the output i need.
Future<String> read(key) async {
final prefs = await SharedPreferences.getInstance();
final value = await prefs.getString(key) ?? '';
return value;
}
When I call this function from my app (this is a simplified snippet):
void onDragEnd(DraggableDetails details, User user) {
final minimumDrag = 100;
Future<String> myvalue;
if (details.offset.dx > minimumDrag) {
user.isSwipedOff = true;
save(user.imgUrl, 'Dog');
}
myvalue = read(user.imgUrl);
print(myvalue);
It's printing :
Instance of 'Future'
Whereas I want myvalue to be 'Dog'... Appreciate any insights!!
Really appreciate your answer #Stijn2202
Solution was to edit the method definition:
Future<void> onDragEnd(DraggableDetails details, User user) async
and then call the read function from the method with this:
final String myvalue = await read(user.imgUrl);
getString is a Future, which you can handle by using await or as you are doing, using then
However, in my opinion using await is your better option. This would look like this:
Future<String> getMyString() async {
final prefs = await SharedPreferences.getInstance();
final value = await prefs.getString(key) ?? '';
// Don't use 0, since it isnt an int what you want to return
return value;
}
EDIT:
based on your code snippet, this is how you should call your read method:
Future<void> onDragEnd(DraggableDetails details, User user) async {
final minimumDrag = 100;
if (details.offset.dx > minimumDrag) {
user.isSwipedOff = true;
save(user.imgUrl, 'Dog');
}
final String myvalue = await read(user.imgUrl);
print(myvalue);
}
Now I'm not sure if onDragEnd is actually allowed to be Future<void>, but let me know if it isn't
Just await for the value. It will return Dog and not instance of Future.
String someName=await myvalue;
As the value is Future, await keyword will wait until the task finishes and return the value

Flutter : How to use SharedPreference to get List<String>?

I've create an initState in my page and call callData to get favId (type : List) every I open this page. But, when the application start, my compiler show this error message :
_TypeError (type 'List<String>' is not a subtype of type 'String')
and this is my getData's function :
getData(favId) async {
SharedPreferences pref = await SharedPreferences.getInstance();
return pref.getStringList(favId);
}
also this is my saveData's function :
void saveData() async {
SharedPreferences pref = await SharedPreferences.getInstance();
pref.setStringList("id", favId);
}
How to fix this problem and I can call getData every I open this page in my application?
Thank you :)
if you want to save and retrieve List to and from SharedPreferences, you to use same key to save and retrieve the value.
here is a simple example,
const favKey = 'favoriteKey';
To save data,
void saveData(String favKey, List<String> favorites) async {
SharedPreferences pref = await SharedPreferences.getInstance();
pref.setStringList(favKey,favorites);
}
To retrive data,
getData(String favKey) async {
SharedPreferences pref = await SharedPreferences.getInstance();
return pref.getStringList(favKey);
}
Note: You need to use same key to set and get data using SharedPreference.
"id" is a String, you need to store a List<String> into setStringList
There are the steps if you want to add an item to the list:
List<String> ids = await getData(favId);
ids.add("id");
saveData(ids, favId);
then change the saveData() to
void saveData(ids, favId) async {
SharedPreferences pref = await SharedPreferences.getInstance();
pref.setStringList(ids, favId);
}
getData()
List<String> getData(favId) async {
SharedPreferences pref = await SharedPreferences.getInstance();
return pref.getStringList(favId);
}

Instance of 'Future<String>' instead of showing the value

Iam using flutter and I am trying to get a value from shared_preferences that I had set before, and display it in a text widget. but i get Instance of Future<String> instead of the value. here is my code:
Future<String> getPhone() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String patientPhone = prefs.getString('patientPhone').toString();
print(patientPhone);
return patientPhone;
}
Future<String> phoneOfPatient = getPhone();
Center(child: Text('${phoneOfPatient}'),))
There is await missing before prefs.getString( and use setState() instead of returning the value. build() can't use await.
String _patientPhone;
Future<void> getPhone() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String patientPhone = await /*added */ prefs.getString('patientPhone');
print(patientPhone);
setState(() => _patientPhone = patientPhone);
}
build() {
...
Center(child: _patientPhone != null ? Text('${_patientPhone}') : Container(),))
}
If you don't have the option to use await or async you can do the following.
getPhone().then((value){
print(value);
});
and then assign a variable to them. From that, you'll have the result from the value.