Can i store a List<dynamic> with shared preference - dart

I will like to store a list of values from an API locally. Does shared preference allow storing List because each time i try to save my values in shared preference, i get " type 'List' is not a subtype of type 'List'"
Future fetchAllProduct() async{
try{
for(int j = 1; j < 3; j++){
final response = await
http.get('https://website/api/?page=1',
);
List result = json.decode(response.body);
products.addAll(result);
//Saving fetched product list
SharedPreferences preferences = await SharedPreferences.getInstance();
preferences.setStringList('prds', products);
//final prds = preferences.getStringList('prd');
}
}catch (ex){
print('$ex');
}
print(products);
}
I'am expecting to see a list like this
[{ProductID: 155, Name: Multi-vit, Description: Multi-vit, CostPrice: 0.0, SalePrice: 80, EatOutPrice: 80, CategoryID: 976, Barcode: , TaxRateID: null, }]

According to shared_preference's repo it should be possible to store a List. Their test case have a slightly different syntax than yours:
preferences.setStringList('List', kTestValues2['flutter.List']) which is different from your approach.
I assume you have defined products as a List.
EDIT:
Why are you storing a list inside a list? What happens if you make your result a String?

An easy way would be to encode the List as a JSON and save that as a string.
import 'dart:convert' show json;
import 'package:shared_preferences/shared_preferences.dart';
void setList(String key, List<dynamic> value) async {
await setString(key, json.encode(value));
}
setList('key', []);

Related

How Can I get a List object by HttpClientResponse?

How can I get a List object in "result"? I tried with toList() method on "request" object, but I can't solve this.
import 'dart:io';
import 'dart:convert';
void main() async {
var request = await HttpClient().getUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts')); // produces a request object
var response = await request.close(); // sends the request
// transforms and prints the response
var result;
await for (var contents in response.transform(Utf8Decoder())) {
result =contents;
}
print(result);
}
Thanks,
Daniel
Firstly, response.transform return multiple parts of result, you need to get all by joining them together:
var result = new StringBuffer();
await for (var contents in response.transform(Utf8Decoder())) {
result.write(contents);
}
Secondly, you result is just a "text" (in json format), not an "object" as you expect, you need to decode it:
List<dynamic> myList = jsonDecode(result.toString());
print(myList);
Simply the following
List elements = json.decode(response.body);

Flutter: shared preferences

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.
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
Shared Preferences Service in Flutter for Code Maintainability
Documentation: Storing key-value data on disk
What are the ?? double question marks in Dart?
How to create an empty list in Dart
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");

Dart - is it possible to change a future.forEach. to a map?

So basically i have this piece of working code:
List<User> users = List();
await Future.forEach(querySnapshot.documents, (doc) async {
final snapshot = await doc['user'].get();
users.add(User(id: snapshot["id"], name: snapshot["mail"]));
});
return users;
It's working fine and does exactly what I need but I was wondering if there was a way to somehow change it to a map, such as:
return querySnapshot.documents.map((doc) async {
final snapshot = await doc['user'].get();
User(id: snapshot["id"], name: snapshot["mail"]);
}).toList{growable: true};
The problem when I do that is that it says: a value of type List< Future< Null>> can't be assigned to a variable of type List< User>.
So I was wondering if it was possible or if the only way is with a Future.forEach
To turn a list of Futures into a single Future, use Future.wait from dart:async. (Also don't forget to return the user object).
final List<User> = await Future.wait(querySnapshot.documents.map((doc) async {
final snapshot = await doc['user'].get();
return User(id: snapshot["id"], name: snapshot["mail"]);
}));

How to select an item from a List in flutter

I have list from a model like this
amount:"12000"
dateTime:"19/07/2018"
detail:"Soto"
hashCode:853818549
id:1
name:"Theodorus"
I want to just select amount and add it to another list of string, but I'm always getting this error A value of type 'String' can't be assigned to a variable of type 'List<String>'. , I thinks its because im not doing it right, here is my code below
void setupList() async {
DebtDatabase db = DebtDatabase();
listCache = await db.getMyDebt();
setState(() {
filtered = listCache;
});
List<String> amount = new List<String>();
listCache.map((value) {
amount = value.amount; } );
//print(amount);
}
can anyone help me, so I can get list of ammount from this model list and then sum all the ammount?
The map function returns an iterable and you can then transform it into a list.
You should try something like this:
void setupList() async {
DebtDatabase db = DebtDatabase();
listCache = await db.getMyDebt();
setState(() {
filtered = listCache;
});
List<String> amount = listCache.map((value) => value.amount).toList();
//print(amount);
}

Dart 2 and parsing json

Im trying to parse json into a list of Products using Dart 2 for web.
I have the following Class:
class Product {
final String Problem;
final String Owner;
final String Description;
const Product({
this.Problem,
this.Owner,
this.Description,
});
factory Product.parse(Map<String, dynamic> json) {
print(json);
return new Product(
Problem: json["Problem"],
Owner: json["Owner"],
Description: json["Description"]
);
}
}
And I am trying to parse this using:
Stream<Product> getProducts() async* {
final payload = await HttpRequest.getString("products.json");
print(payload);
//var _json = (json.decode(payload));
print("break");
var list = json.decode(payload);
print(list);
//print(list);
final productList = (json.decode(payload) as List).cast<Map<String, dynamic>>();
}
However this fails with this error:
EXCEPTION: Type '_JsonMap' is not a subtype of expected type
'List'.
I can see that I have a list[Symbol(_original)] when I debug, but when I try to evaluate this, I returns as undefined.
I also tried
List list = json.decode(payload) as List;
List<dynamic> list = json.decode(payload);
List<dynamic> list = json.decode(payload) as List<dynamic>;
var list = (json.decode(payload)).cast<Map<String, dynamic>>();
var list = (json.decode(payload)).cast<Map<dynamic, dynamic>>();
but get the same error.
Json
{
"Product_One": {
"Owner": "test",
"Description": "test description",
"Theme_Objective": "test objective",
"Technical_details": "test technical details",
"Problem": "test",
"Solution": "test"
}
}
Your JSON does not contain any list, it's all maps.
When you try to cast a Map to List, it has to fail since maps are not lists.
Maybe you want to do:
final productList = (jsonDecode(payload) as Map).values.toList();
This gives you a list of the product maps, without the names that you don't appear to be using anyway.

Resources