Type 'List<dynamic>' is not a subtype of type 'List<SubCategoryData>' - flutter

I am trying to assigning the list to list of object, but it is showing the above exception.
List<SubCategoryData>categoryNames = new List<SubCategoryData>();
List<String>categorieslist = [];
bool isFirst=true;
Future<SubCategoryModel>fetchCategories(BuildContext context) async {
String url = "http://106.51.64.251:380/onnet_api/subcatListByCategory.php";
var body = new Map<String,String>();
body['publisherid']= 102.toString();
body['tag'] = "category";
body['subtag']= "list";
body['parentId'] = 10.toString();
http.Response res = await http.post(url,body: body);
final categoryjsondata = json.decode(res.body);
var map = Map<String,dynamic>.from(categoryjsondata);
var categoryResponse = SubCategoryModel.fromJson(map);
if(res.statusCode == 200){
print('category Response: $categoryResponse');
if(categoryResponse.status == 1){
//final categoryModel = json.decode(res.body);
categoryNames = categoryjsondata['data']as List;
print('category data: $categoryNames');
/* for(var model in categorieslist){
categoryNames.add(new SubCategoryData.fromJson(model));
}*/
/* SharedPreferences prefs = await SharedPreferences.getInstance();
print("cat List Size: $categories");
prefs.setStringList("categorylist", categories);*/
Navigator.push(context, MaterialPageRoute(builder: (context)=> ChewieDemo(imageData: images[0],
categoryData:categoryNames.toList())));
}
}
}
By seeing my code, for categoryNames I am trying to assigning the data to this then it is showing the exception.

Try to change your code to:
List<SubCategoryData> categoryNames = new ArrayList<>();
Hopefully this will solve your problem.

replace the following:
categoryNames = categoryjsondata['data']as List;
by
for(var model in categoryData){
categoryNames.add(new SubCategoryData.fromJson(model));
}
because the first returns a List the second returns a List

Your problem resides here:
categoryNames = categoryjsondata['data']as List;
categoryNames is already defined and initialized and its type is List<SubCategoryData>. In the line above you are trying to assign a List<dynamic> to it. That's a different type and that's the cause of the error. If you assign that to some other variable you can use it freely:
final categoryNamesList = categoryjsondata['data'] as List;
BTW then you don't have to call .toList() in the next lines, because this variable is already a list.

If explicity not defined the lists are of type dynamic, So explicitly state the value of the model. i.e
Convert
categoryNames = categoryjsondata['data']as List;
to
categoryNames = List<SubCategoryData>.from(categoryjsondata['data']);

Related

setter error in flutter while assigning value to class variable In flutter

I have created a demo where I am storing data in divide using sqfliteHelper and I want to create a object list to store data in memory for temporary use but I am getting error while assigning value to class variable, regarding setter required
here is my code
class SqfliteProvider {
List<CategoryModel> _categorylist = [];
List<CategoryModel> get categories {
return _categorylist;
}
static Future<List<CategoryModel>?> fetchcategory() async {
final db = await _getdb();
List<CategoryModel> templist = [];
List<Map<String, dynamic>> maplist = await db.query('categorytb');
if (maplist.isEmpty) return null;
templist = maplist.map((e) => CategoryModel.frommap(e)).toList();
//this statement showing an error ...required setter..
_categorylist = templist;
return templist;
}
}

How to Save List in SharedPreferences in Flutter

Hello all at first I want to mention that I've tried a lot of solutions here but it didn't work for me.
I bring the list from the database through the following code:
var listCat = [];
Future getdata() async {
apiURL = '***************.php';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listCat.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
}
return responsebody;
}else{
}
}
As is obvious in the code above I am trying to get the name and image and this is not a problem right now I want to store this listCat in SharedPreferences until I recall it from all pages of the app
I have the following class to save SharedPreferences:
class APIPreferences {
static SharedPreferences ? _preferences;
static const _keyMuinCat = 'MuinCat';
static Future init() async => _preferences = await SharedPreferences.getInstance();
static Future setMuinCat(String MuinCat) async => await _preferences!.setString(_keyMuinCat, MuinCat);
static String? getMuinCat() => _preferences!.getString(_keyMuinCat);
}
Then I save what I need to save by the following line:
APIPreferences.setMuinCat(listCat.toString());
Then I can bring pre-stored data from any location where I need it through the following code:
CatList = APIPreferences.getMuinCat() ?? '';
I tried to do the following thing now to save the list in the first code above:
var listCat = [];
Future getdata() async {
apiURL = '***************.php';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listCat.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
APIPreferences.setMuinCat(listCat.toString());
}
return responsebody;
}else{
}
}
But it didn't work. I don't really know how to deal with it.
How can I save it and then bring it to use with ListView.
instead of:
_preferences!.setString(_keyMuinCat, "some string");
use:
_preferences!.setStringList(_keyMuinCat, ["some", "strings", "in", "list"]);
So in your code, the setMuinCat method needs to be:
static Future setMuinCat(List<String> muinCat) async => await _preferences!.setStringList(_keyMuinCat, muinCat);
and then you call it like this:
APIPreferences.setMuinCat((listCat as List).map((v) => v.toString()).toList());
To save the list in shared preferences you need to pass as jsonEncode(yourList data) and when you will fecth the shared list you will again jsonDecode(your list)
await prefs.setString('YOUR KEY', json.encode(YOURMAP()));

Exception in json.decode : Closure: () => String from Function 'toString'

I am getting some data from API in flutter. I am trying to decode the data using json.decode() but this decode function gives me the following error:
Closure: () => String from Function 'toString'
Here's my code:
Future<Product> createOrder() async {
var client = new http.Client();
var productModel = null;
try {
var response = await client
.get(Uri.https('butterbasket.onrender.com', Strings.createOrderUrl));
if (response.statusCode == 200) {
var body = response.body;
print("Body: $body");
var jsonMap = json.decode(body);
var productModel = Product.fromJson(jsonMap);
}
} catch (e) {
print("Exception: ${e.toString}");
}
return productModel;
}
Here is the Error Debug Console:
You are running into issues because the data you are loading in is an array, but the model is an object. You'll need to do something like the following:
final List jsonProducts = json.decode(body)
final List<Product> products =
jsonProducts.map((jsonProduct) => Product.fromJson(jsonProduct)).toList();
and then if you only need the first item you can do:
final Product product = products[0]
But don't forget to check if the array is big enough.
Your Future function must return an optional Product?, otherwise your future will never find a result as you are declaring it inside the function.
Instead of:
Future<Product> createOrder() async {}
Use:
Future<Product?> createOrder() async {}
Finally your async snapshot and FutureBuilder type should be of type <Product?>.

Flutter - await/async on a List - why does this only work when not using declarations?

Still new to Flutter :(. Can anyone help...
I have a class that stores a bunch of project information. One part of this is a list of topics (for push notification), which it grabs from a JSON file.
I apply a getter for the list of topics, and when getting it it calls an async function which will return a List
Future<List<String>> _pntopics() async{
final _json = await http.get(Uri.parse(_topicsUrl));
if (_json.statusCode == 200) {
return (jsonDecode(_json.body));
}else {
return [""];
}
}
Future<List<String>> get topics => _pntopics();
In my main.dart file, it calls this value like so...
Future<List<String>> _topiclist = await projectvalues.topics;
The response is however empty, pressumably because it is a Future - so it is grabbing the empty value before it is filled.
But I can't remove the "Future" part from the async method, because asnc methods require a Future definition.
Then I decided to remove the declarations entirely:
_pntopics() async{
final _json = await http.get(Uri.parse(_topicsUrl));
if (_json.statusCode == 200) {
return (jsonDecode(_json.body));
}else {
return [""];
}
}
get topics => _pntopics();
and in main.dart, a general declaration...
var _topiclist = await projectvalues.topics;
...and this works!
So what declaration should I actually be using for this to work? I'm happy to not use declarations but we're always to declare everthing.
You should return back Future<List<String>> return types to the function and the getter but for _topicslist you must use var, final or List<String> declaration because:
(await Future<T>) == T
i.e.
var _topiclist = await projectvalues.topics; // The type of _topiclist is List<String>
final _topiclist = await projectvalues.topics; // The type of _topiclist is List<String>
UPDATE
Your code should be:
Future<List<String>> _pntopics() async{
final _json = await http.get(Uri.parse(_topicsUrl));
if (_json.statusCode == 200) {
return List<String>.from(jsonDecode(_json.body));
}else {
return <String>[""];
}
}
Doing this you force _pnptopics returns List<String> as jsonDecode returns List<dynamic>.
P.S. It is good practice do not use dynamic types where they can be changed to specified types.

Trying to create a method to store Strings in a list

i have a list of volumes that looks like this
['9v9JXgmM3F0C','RoAwAAAAYAAJ','RYAwAAAAYAAJ']
i have a ready funtion that sends Individual volumes and retruns a Map.
Future<BookIdVolume> getBooksByVolume(volume) async {
var searchUrl = 'https://www.googleapis.com/books/v1/volumes/$volume';
var response = await http.get(searchUrl);
var responseBody = jsonDecode(response.body);
return BookIdVolume.fromJson(responseBody);
}
Im trying to create a method to store each of volumes in a list and retrun it.
I have tryed using loops for and forEach but it keeps retruning either [] or null
im i doing somthing wong ? is thier a better better way to do it ?
I'm guessing you're getting null back because you're not building the url properly for each volume. Try this.
final volumeList = ['9v9JXgmM3F0C', 'RoAwAAAAYAAJ', 'RYAwAAAAYAAJ'];
final baseUrl = 'https://www.googleapis.com/books/v1/volumes/';
List<BookIdVolume> bookList = [];
void buildBookList() async {
for (String volume in volumeList) {
final url = '$baseUrl$volume';
final book = await getBooksByVolume(url);
bookList.add(book);
}
}
Then you remove the first line from the getBooksByVolume function because you're already sending the full url.
Future<BookIdVolume> getBooksByVolume(url) async {
var response = await http.get(url);
var responseBody = jsonDecode(response.body);
return BookIdVolume.fromJson(responseBody);
}