How to display Nested api data using model class in listview in Flutter? - flutter

I am tried to display data in listview.
I have Json Response as below.
[
{
"success": 1,
"subject": [
{
"subject_id": "5e32874c714fa",
"subject_name": "Account",
"image": "upload/subject/Account.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
},
{
"subject_id": "5da9ff659fb7c",
"subject_name": "Biology",
"image": "upload/subject/03_logo-1164x484.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
},
{
"subject_id": "5da9ff990b1c6",
"subject_name": "Chemisty",
"image": "upload/subject/02_logo-1168x490.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
},
{
"subject_id": "5de76afbd064e",
"subject_name": "Computer",
"image": "upload/subject/07_logo-1169x486.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
},
{
"subject_id": "5d788906c431b",
"subject_name": "Devsatya Paperset March 2020",
"image": "upload/subject/04_logo-1174x491.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
}
]
}
]
as above response i create a model class as below
// To parse this JSON data, do
//
// final subjectByUser = subjectByUserFromJson(jsonString);
import 'dart:convert';
List<SubjectByUser> subjectByUserFromJson(String str) =>
List<SubjectByUser>.from(
json.decode(str).map((x) => SubjectByUser.fromJson(x)));
String subjectByUserToJson(List<SubjectByUser> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class SubjectByUser {
SubjectByUser({
required this.success,
required this.subject,
});
int success;
List<Subject> subject;
factory SubjectByUser.fromJson(Map<String, dynamic> json) => SubjectByUser(
success: json["success"],
subject:
List<Subject>.from(json["subject"].map((x) => Subject.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"success": success,
"subject": List<dynamic>.from(subject.map((x) => x.toJson())),
};
}
class Subject {
Subject({
required this.subjectId,
required this.subjectName,
required this.image,
required this.active,
required this.standardId,
required this.mediumId,
});
String subjectId;
String subjectName;
String image;
String active;
String standardId;
String mediumId;
factory Subject.fromJson(Map<String, dynamic> json) => Subject(
subjectId: json["subject_id"],
subjectName: json["subject_name"],
image: json["image"],
active: json["active"],
standardId: json["standard_id"],
mediumId: json["medium_id"],
);
Map<String, dynamic> toJson() => {
"subject_id": subjectId,
"subject_name": subjectName,
"image": image,
"active": active,
"standard_id": standardId,
"medium_id": mediumId,
};
}
I write below code, now how can i display subjects data like subjectName, image, etc in list view?
in print i can get the subject name on index 3.
Future getUserSubject(List subject) async {
final subjectUrl =
"$baseUrl/subject/get_by_user_plan?user_id=609cab2cd5b6c&order_id=1620889722609cd07a601af469889697609cab2cd5b6c&standard_id=5d1594e283e1a&medium_id=5d15938aa1344";
final response = await http.get(Uri.parse(subjectUrl));
final subjects = response.body;
final decodedData = jsonDecode(subjects);
SubjectByUserModel subjectByUserModel =
SubjectByUserModel.fromJson(decodedData);
print(subjectByUserModel.subject?[2].subjectName);
}
I put all codes in separate file also view

You can use ListView.builder
ListView.builder(
itemCount: subjectByUserModel.subject ?? 0,
itemBuilder: (BuildContext context, int index) {
print(subjectByUserModel.subject?[index].subjectName);
print(subjectByUserModel.subject?[index].standardId); // so on
// Now you can build any widget for per subject.
// like card, listTile or simple text.
return Text('');
});

Related

how to get data from nested json input from flutter?

Below is the response how to get this data in flutter.I wants to get image file path of all fields like aadhaar,pan card and business ownership proof. I needs to know how to get the response when it is structured like this?
{
"data": {
"pan": {
"verified": true,
"status": "Approve",
"comment": "ok",
"holder": "VISHWAJEET VIJAY KOLAPKAR",
"number": "DYPPK8990B",
"files": [...,...]
},
"aadhar": {
"verified": true,
"status": "Approved",
"comment": "ok",
"holder": "",
"number": "000000001112",
"address": "",
"dob": "Not available on aadhaar",
"gender": "MALE",
"files": [...,...]
},
"mobile": {
"verified": true,
"status": "In-Progress",
"comment": "",
"number": "9527796311",
"countryCode": "91",
"holder": "Aniket Ratnakar Baviskar",
"address": "Plot no.57,, Margashirsh sector, Datt chouk, Cidco, Nashik, Mh-422009",
"email": "baviskaranu#gmail.com"
},
"faceMatch": {
"verified": "true",
"status": "In-Progress",
"comment": "",
"holder": "Vodafone Vk",
"matchPercentage": "100.00%",
"message": "Verification completed with positive result",
"dob": "NA",
"files": [...,...]
},
"address": {
"status": "Approved",
"comment": "ok",
"verified": false,
"files": [...,...]
},
"bankStatement": {
"comment": "ok",
"status": "Approved",
"verified": false,
"files": [...,...]
},
"business": {
"documentNumber": "8877",
"documentType": "Board Resolution (for companies)",
"status": "Approved",
"verified": false,
"files": [...,...]
},
"financial": {
"comment": "ok",
"status": "Approved",
"verified": false,
"files": [...,...]
},
"gst": {
"verified": false,
"files": [...,...]
},
"ownership": {
"documentNumber": "55555",
"documentType": "Electricity Bill",
"status": "Approved",
"verified": false,
"files": [...,...]
},
"partnership": {
"comment": "ok",
"status": "Approved",
"verified": false,
"files": [...,...]
},
"vintage": {
"status": "Approved",
"verified": false,
"files": [...,...]
},
"storeImages": {
"comment": "ok",
"status": "Approved",
"verified": false,
"files": [...,...]
}
},
"status": true
}
after you get the data pass it to this function
final yourModel = yourModelFromMap(jsonString);
it will parse json to this object
and you can use it like
yourModel.data.<any value you want>
.
import 'dart:convert';
YourModel yourModelFromMap(String str) => YourModel.fromMap(json.decode(str));
String yourModelToMap(YourModel data) => json.encode(data.toMap());
class YourModel {
YourModel({
required this.data,
required this.status,
});
Data data;
bool status;
factory YourModel.fromMap(Map<String, dynamic> json) => YourModel(
data: Data.fromMap(json["data"]),
status: json["status"],
);
Map<String, dynamic> toMap() => {
"data": data.toMap(),
"status": status,
};
}
class Data {
Data({
required this.pan,
required this.aadhar,
required this.mobile,
required this.faceMatch,
required this.address,
required this.bankStatement,
required this.business,
required this.financial,
required this.gst,
required this.ownership,
required this.partnership,
required this.vintage,
required this.storeImages,
});
Pan pan;
Aadhar aadhar;
Mobile mobile;
FaceMatch faceMatch;
Address address;
Address bankStatement;
Business business;
Address financial;
Gst gst;
Business ownership;
Address partnership;
Vintage vintage;
Address storeImages;
factory Data.fromMap(Map<String, dynamic> json) => Data(
pan: Pan.fromMap(json["pan"]),
aadhar: Aadhar.fromMap(json["aadhar"]),
mobile: Mobile.fromMap(json["mobile"]),
faceMatch: FaceMatch.fromMap(json["faceMatch"]),
address: Address.fromMap(json["address"]),
bankStatement: Address.fromMap(json["bankStatement"]),
business: Business.fromMap(json["business"]),
financial: Address.fromMap(json["financial"]),
gst: Gst.fromMap(json["gst"]),
ownership: Business.fromMap(json["ownership"]),
partnership: Address.fromMap(json["partnership"]),
vintage: Vintage.fromMap(json["vintage"]),
storeImages: Address.fromMap(json["storeImages"]),
);
Map<String, dynamic> toMap() => {
"pan": pan.toMap(),
"aadhar": aadhar.toMap(),
"mobile": mobile.toMap(),
"faceMatch": faceMatch.toMap(),
"address": address.toMap(),
"bankStatement": bankStatement.toMap(),
"business": business.toMap(),
"financial": financial.toMap(),
"gst": gst.toMap(),
"ownership": ownership.toMap(),
"partnership": partnership.toMap(),
"vintage": vintage.toMap(),
"storeImages": storeImages.toMap(),
};
}
class Aadhar {
Aadhar({
required this.verified,
required this.status,
required this.comment,
required this.holder,
required this.number,
required this.address,
required this.dob,
required this.gender,
required this.files,
});
bool verified;
String status;
String comment;
String holder;
String number;
String address;
String dob;
String gender;
List<dynamic> files;
factory Aadhar.fromMap(Map<String, dynamic> json) => Aadhar(
verified: json["verified"],
status: json["status"],
comment: json["comment"],
holder: json["holder"],
number: json["number"],
address: json["address"],
dob: json["dob"],
gender: json["gender"],
files: List<dynamic>.from(json["files"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"verified": verified,
"status": status,
"comment": comment,
"holder": holder,
"number": number,
"address": address,
"dob": dob,
"gender": gender,
"files": List<dynamic>.from(files.map((x) => x)),
};
}
class Address {
Address({
required this.status,
required this.comment,
required this.verified,
required this.files,
});
String status;
String comment;
bool verified;
List<dynamic> files;
factory Address.fromMap(Map<String, dynamic> json) => Address(
status: json["status"],
comment: json["comment"],
verified: json["verified"],
files: List<dynamic>.from(json["files"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"status": status,
"comment": comment,
"verified": verified,
"files": List<dynamic>.from(files.map((x) => x)),
};
}
class Business {
Business({
required this.documentNumber,
required this.documentType,
required this.status,
required this.verified,
required this.files,
});
String documentNumber;
String documentType;
String status;
bool verified;
List<dynamic> files;
factory Business.fromMap(Map<String, dynamic> json) => Business(
documentNumber: json["documentNumber"],
documentType: json["documentType"],
status: json["status"],
verified: json["verified"],
files: List<dynamic>.from(json["files"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"documentNumber": documentNumber,
"documentType": documentType,
"status": status,
"verified": verified,
"files": List<dynamic>.from(files.map((x) => x)),
};
}
class FaceMatch {
FaceMatch({
required this.verified,
required this.status,
required this.comment,
required this.holder,
required this.matchPercentage,
required this.message,
required this.dob,
required this.files,
});
String verified;
String status;
String comment;
String holder;
String matchPercentage;
String message;
String dob;
List<dynamic> files;
factory FaceMatch.fromMap(Map<String, dynamic> json) => FaceMatch(
verified: json["verified"],
status: json["status"],
comment: json["comment"],
holder: json["holder"],
matchPercentage: json["matchPercentage"],
message: json["message"],
dob: json["dob"],
files: List<dynamic>.from(json["files"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"verified": verified,
"status": status,
"comment": comment,
"holder": holder,
"matchPercentage": matchPercentage,
"message": message,
"dob": dob,
"files": List<dynamic>.from(files.map((x) => x)),
};
}
class Gst {
Gst({
required this.verified,
required this.files,
});
bool verified;
List<dynamic> files;
factory Gst.fromMap(Map<String, dynamic> json) => Gst(
verified: json["verified"],
files: List<dynamic>.from(json["files"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"verified": verified,
"files": List<dynamic>.from(files.map((x) => x)),
};
}
class Mobile {
Mobile({
required this.verified,
required this.status,
required this.comment,
required this.number,
required this.countryCode,
required this.holder,
required this.address,
required this.email,
});
bool verified;
String status;
String comment;
String number;
String countryCode;
String holder;
String address;
String email;
factory Mobile.fromMap(Map<String, dynamic> json) => Mobile(
verified: json["verified"],
status: json["status"],
comment: json["comment"],
number: json["number"],
countryCode: json["countryCode"],
holder: json["holder"],
address: json["address"],
email: json["email"],
);
Map<String, dynamic> toMap() => {
"verified": verified,
"status": status,
"comment": comment,
"number": number,
"countryCode": countryCode,
"holder": holder,
"address": address,
"email": email,
};
}
class Pan {
Pan({
required this.verified,
required this.status,
required this.comment,
required this.holder,
required this.number,
required this.files,
});
bool verified;
String status;
String comment;
String holder;
String number;
List<dynamic> files;
factory Pan.fromMap(Map<String, dynamic> json) => Pan(
verified: json["verified"],
status: json["status"],
comment: json["comment"],
holder: json["holder"],
number: json["number"],
files: List<dynamic>.from(json["files"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"verified": verified,
"status": status,
"comment": comment,
"holder": holder,
"number": number,
"files": List<dynamic>.from(files.map((x) => x)),
};
}
class Vintage {
Vintage({
required this.status,
required this.verified,
required this.files,
});
String status;
bool verified;
List<dynamic> files;
factory Vintage.fromMap(Map<String, dynamic> json) => Vintage(
status: json["status"],
verified: json["verified"],
files: List<dynamic>.from(json["files"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"status": status,
"verified": verified,
"files": List<dynamic>.from(files.map((x) => x)),
};
}

type '(dynamic) => Product' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform'

I am trying to consume data from an API. I used quicktype.io to create a model class to parse the JSON data. The JSON data contains nested maps.
Now I am getting an error
The error is [type '(dynamic) => Product' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform']
This is the code for API request;
Future<void> setSpecials(String restaurantId) async {
try {
final url = Uri.parse(
ENDPOINT + 'restaurant/specials?restaurantId=$restaurantId&page=0');
final response = await http.get(url);
print(response.statusCode);
if (response.statusCode == 200) {
final List<Product> specials = productFromJson(response.body);
_specialsList = specials;
}
print(_specialsList.length);
notifyListeners();
} catch (e) {
print(e.toString());
}}
This is the model
List<Product> productFromJson(String str) => List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));
String productToJson(List<Product> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Product {
Product({
required this.id,
required this.name,
required this.image,
required this.description,
required this.isFavourite,
required this.dishes,
required this.diet,
});
String id;
String name;
String image;
String description;
bool isFavourite;
List<Dish> dishes;
String diet;
factory Product.fromJson(Map<String, dynamic> json) => Product(
id: json["_id"],
name: json["name"],
image: json["image"],
description: json["description"],
isFavourite: json["isFavourite"],
dishes: List<Dish>.from(json["dishes"].map((x) => Dish.fromJson(x))),
diet: json["diet"] == null ? null : json["diet"],
);
Map<String, dynamic> toJson() => {
"_id": id,
"name": name,
"image": image,
"description": description,
"isFavourite": isFavourite,
"dishes": List<dynamic>.from(dishes.map((x) => x.toJson())),
"diet": diet == null ? null : diet,
};
}
class Dish {
Dish({
required this.name,
required this.price,
required this.offerIds,
required this.id,
});
String name;
double price;
List<dynamic> offerIds;
String id;
factory Dish.fromJson(Map<String, dynamic> json) => Dish(
name: json["name"],
price: double.parse(json["price"].toString()),
offerIds: List<dynamic>.from(json["offerIds"].map((x) => x)),
id: json["_id"],
);
Map<String, dynamic> toJson() => {
"name": name,
"price": price,
"offerIds": List<dynamic>.from(offerIds.map((x) => x)),
"_id": id,
};
}
The JSON data is
[
{
"_id": "60edb147d91f7820c80585c9",
"name": "Chicken Biriyani",
"image": "localhost:3031\\images\\1626190484369-chicken-Biryani.jpg",
"description": "Chicken, Motton",
"isFavourite": false,
"dishes": [
{
"name": "Full",
"price": 200,
"offerIds": [],
"_id": "610e1cd618319924b45ef9cd"
},
{
"name": "Half",
"price": 150,
"offerIds": [],
"_id": "610e1cd618319924b45ef9ce"
},
{
"name": "Quarter",
"price": 100,
"offerIds": [],
"_id": "610e1cd618319924b45ef9cf"
}
]
},
{
"_id": "610cb83c231052429899df76",
"name": "Shavrma",
"image": "157.245.96.189:3031/images/1632371901688-IMG-20210922-WA0123.jpg",
"description": "Chicken Shavrma",
"diet": "Veg",
"isFavourite": false,
"dishes": [
{
"name": "Plate",
"price": 80,
"offerIds": [],
"_id": "610cb83c231052429899df77"
},
{
"name": "Roll",
"price": 60,
"offerIds": [],
"_id": "610cb83c231052429899df78"
}
]
}
]

Invalid argument(s): No host specified in URI file:/// Error

I got error
invalid argument(s): No host specified in URI file:///upload/subject/Account.png
I got other all data from api but when I fetch an image it throws above error.
Json response as below.
{
"success": 1,
"subject": [
{
"subject_id": "5e32874c714fa",
"subject_name": "Account",
"image": "upload/subject/Account.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
},
{
"subject_id": "5da9ff659fb7c",
"subject_name": "Biology",
"image": "upload/subject/03_logo-1164x484.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
},
{
"subject_id": "5da9ff990b1c6",
"subject_name": "Chemisty",
"image": "upload/subject/02_logo-1168x490.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
},
{
"subject_id": "5de76afbd064e",
"subject_name": "Computer",
"image": "upload/subject/07_logo-1169x486.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
},
{
"subject_id": "5d788906c431b",
"subject_name": "Devsatya Paperset March 2020",
"image": "upload/subject/04_logo-1174x491.png",
"active": "1",
"standard_id": "5d1594e283e1a",
"medium_id": "5d15938aa1344"
}
]
}
And i created Model Class from app.quicktype.io/ as below.
// To parse this JSON data, do
//
// final subjectByUser = subjectByUserFromJson(jsonString);
import 'dart:convert';
SubjectByUser subjectByUserFromJson(String str) => SubjectByUser.fromJson(json.decode(str));
String subjectByUserToJson(SubjectByUser data) => json.encode(data.toJson());
class SubjectByUser {
SubjectByUser({
this.success,
this.subject,
});
int success;
List<Subject> subject;
factory SubjectByUser.fromJson(Map<String, dynamic> json) => SubjectByUser(
success: json["success"],
subject: List<Subject>.from(json["subject"].map((x) => Subject.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"success": success,
"subject": List<dynamic>.from(subject.map((x) => x.toJson())),
};
}
class Subject {
Subject({
this.subjectId,
this.subjectName,
this.image,
this.active,
this.standardId,
this.mediumId,
});
String subjectId;
String subjectName;
String image;
String active;
String standardId;
String mediumId;
factory Subject.fromJson(Map<String, dynamic> json) => Subject(
subjectId: json["subject_id"],
subjectName: json["subject_name"],
image: json["image"],
active: json["active"],
standardId: json["standard_id"],
mediumId: json["medium_id"],
);
Map<String, dynamic> toJson() => {
"subject_id": subjectId,
"subject_name": subjectName,
"image": image,
"active": active,
"standard_id": standardId,
"medium_id": mediumId,
};
}
The Function as below.
Future<List<Subject>> getSubjectByUser() async {
final subjectUrl =
'$baseUrl/subject/get_by_user_plan?user_id=609cab2cd5b6c&order_id=1620889722609cd07a601af469889697609cab2cd5b6c&standard_id=5d1594e283e1a&medium_id=5d15938aa1344';
final response = await http.get(Uri.parse(subjectUrl));
if (response.statusCode == 200) {
final subjectData = subjectByUserFromJson(response.body);
final List<Subject> subjects = subjectData.subject;
return subjects;
} else {
return <Subject>[];
}
}
And View code as below.
return ListView.builder(
itemCount: null == _subjects ? 0 : _subjects.length,
//itemCount: _subjects.length,
itemBuilder: (context, index) {
Subject subject = _subjects[index];
return Card(
child: ListTile(
leading: Image.network(subject.image),
title: Text(subject.subjectName),
),
);
});
So how can i get image in list view?
In network image, you just called subject.image that means you call "upload/subject/02_logo-1168x490.png" but you missed adding base url. And you must use shrinkWrap: true under ListView.builder
ListTile(
leading: Image.network("$baseUrl/$"subject.image"),// here will be changed need
title: Text(subject.subjectName),
),
yes it works. Thenk you for your Help.....
It works for me as.
child: Image.network("$imageUrl" + subject.image),

Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic> While working on a Todo App

I am trying to get data from a local API into my project, i am facing the following problem:
Unhandled Exception: type 'List' is not a subtype of type 'Map<String, dynamic>'
// To parse this JSON data, do
//
// final toDo = toDoFromJson(jsonString);
import 'dart:convert';
import 'package:http/http.dart' as http;
ToDo toDoFromJson(String str) => ToDo.fromJson(json.decode(str));
String toDoToJson(ToDo data) => json.encode(data.toJson());
class ToDo {
ToDo({
required this.id,
required this.img,
required this.name,
required this.title,
required this.done,
required this.note,
required this.priority,
required this.dueDate,
required this.taskOwner,
required this.studentId,
required this.createdAt,
required this.updatedAt,
});
int id;
String img;
String name;
String title;
int done;
String note;
String priority;
String dueDate;
int taskOwner;
String studentId;
String createdAt;
String updatedAt;
factory ToDo.fromJson(Map<String, dynamic> json) => ToDo(
id: json["id"],
img: json["img"],
name: json["name"],
title: json["title"],
done: json["done"],
note: json["note"],
priority: json["priority"],
dueDate: json["due_date"],
taskOwner: json["TaskOwner"],
studentId: json["studentId"],
createdAt: json["createdAt"],
updatedAt: json["updatedAt"],
);
Map<String, dynamic> toJson() => {
"id": id,
"img": img,
"name": name,
"title": title,
"done": done,
"note": note,
"priority": priority,
"due_date": dueDate,
"TaskOwner": taskOwner,
"studentId": studentId,
"createdAt": createdAt,
"updatedAt": updatedAt,
};
}
Future<List<ToDo>> fetchTodos() async {
final response =
await http.get(Uri.parse('http://localhost:3000/task/all/1'));
if (response.statusCode == 200) {
final List<ToDo> todo = toDoFromJson(response.body) as List<ToDo>;
print(todo);
return todo;
} else {
print("nothing found");
return [];
}
}
Json from API is as below:
{
"id": 1,
"img": "assets/images/user/user1.jpg",
"name": "task 1",
"title": "eee",
"done": 0,
"note": "eee",
"priority": "Normal",
"due_date": "2021-07-06T18:30:00.000Z",
"TaskOwner": 1,
"studentId": "2",
"createdAt": "2021-07-26T14:39:54.000Z",
"updatedAt": "2021-07-26T14:39:54.000Z"
},
{
"id": 2,
"img": "assets/images/user/user1.jpg",
"name": "task 2",
"title": "nnjn",
"done": 0,
"note": "2525",
"priority": "High",
"due_date": "2021-07-19T18:30:00.000Z",
"TaskOwner": 1,
"studentId": "7",
"createdAt": "2021-07-27T15:05:31.000Z",
"updatedAt": "2021-07-27T15:05:31.000Z"
},
{
"id": 3,
"img": "assets/images/user/user1.jpg",
"name": "task 3",
"title": "5255",
"done": 0,
"note": "55",
"priority": "Normal",
"due_date": "2021-07-21T18:30:00.000Z",
"TaskOwner": 1,
"studentId": "7",
"createdAt": "2021-07-27T15:05:48.000Z",
"updatedAt": "2021-07-27T15:05:48.000Z"
},
{
"id": 4,
"img": "assets/images/user/user1.jpg",
"name": "task 4",
"title": "kaam kro",
"done": 0,
"note": "test note",
"priority": "Normal",
"due_date": "2021-07-21T18:30:00.000Z",
"TaskOwner": 1,
"studentId": "2",
"createdAt": "2021-08-04T14:45:47.000Z",
"updatedAt": "2021-08-04T14:45:47.000Z"
},
The method you are using to parse todos will return a ToDo object casted to a List<ToDo> which will cause an exception!
What you have to do is converting every single map in json to ToDo and then create a List from them.
Here is what you need to do:
replace this line
final List<ToDo> todo = toDoFromJson(response.body) as List<ToDo>;
with this:
final List<ToDo> todo = List<ToDo>.from(response.body.map((x) => toDoFromJson(x)))
fixed this by adding for loop to the Future function, refer to the code below -
Future<List<ToDo>> fetchTodos() async {
List<ToDo> todos = [];
final response =
await http.get(Uri.parse('https://dhulltransport.com:20625/task/all/1'));
if (response.statusCode == 200) {
var jsonList = jsonDecode(response.body);
for (var t in jsonList) {
todos.add(ToDo.fromJson(t));
}
print(todos.length);
return todos;
} else {
return [];
}
}

From a list of YouTube videos rendered in a card stack, the 1st video starts playing in every card on swipe

I am trying to create a Tinder-like swipe functionality with the Youtube videos. I'll provide a detailed description of what I am trying to achieve.
Step by Step breakdown:
Fetch the Youtube videos using the Youtube Data API v3.
youtube _model.dart
// To parse this JSON data, do
//
// final youtubeSearchVideos = youtubeSearchVideosFromJson(jsonString);
import 'dart:convert';
YoutubeSearchVideos youtubeSearchVideosFromJson(String str) =>
YoutubeSearchVideos.fromJson(json.decode(str));
String youtubeSearchVideosToJson(YoutubeSearchVideos data) =>
json.encode(data.toJson());
class YoutubeSearchVideos {
YoutubeSearchVideos({
required this.kind,
required this.etag,
this.nextPageToken,
this.prevPageToken,
required this.regionCode,
required this.pageInfo,
required this.items,
});
String kind;
String etag;
String? nextPageToken;
String? prevPageToken;
String regionCode;
PageInfo pageInfo;
List<Item> items;
factory YoutubeSearchVideos.fromJson(Map<String, dynamic> json) =>
YoutubeSearchVideos(
kind: json["kind"],
etag: json["etag"],
nextPageToken: json["nextPageToken"],
prevPageToken: json["prevPageToken"],
regionCode: json["regionCode"],
pageInfo: PageInfo.fromJson(json["pageInfo"]),
items: List<Item>.from(json["items"].map((x) => Item.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"kind": kind,
"etag": etag,
"nextPageToken": nextPageToken,
"prevPageToken": prevPageToken,
"regionCode": regionCode,
"pageInfo": pageInfo.toJson(),
"items": List<dynamic>.from(items.map((x) => x.toJson())),
};
}
class Item {
Item({
required this.kind,
required this.etag,
required this.id,
required this.snippet,
});
String kind;
String etag;
Id id;
Snippet snippet;
factory Item.fromJson(Map<String, dynamic> json) => Item(
kind: json["kind"],
etag: json["etag"],
id: Id.fromJson(json["id"]),
snippet: Snippet.fromJson(json["snippet"]),
);
Map<String, dynamic> toJson() => {
"kind": kind,
"etag": etag,
"id": id.toJson(),
"snippet": snippet.toJson(),
};
}
class Id {
Id({
required this.kind,
required this.videoId,
});
String kind;
String videoId;
factory Id.fromJson(Map<String, dynamic> json) => Id(
kind: json["kind"],
videoId: json["videoId"],
);
Map<String, dynamic> toJson() => {
"kind": kind,
"videoId": videoId,
};
}
class Snippet {
Snippet({
required this.publishedAt,
required this.channelId,
required this.title,
required this.description,
required this.thumbnails,
required this.channelTitle,
required this.liveBroadcastContent,
required this.publishTime,
});
DateTime publishedAt;
String channelId;
String title;
String description;
Thumbnails thumbnails;
String channelTitle;
String liveBroadcastContent;
DateTime publishTime;
factory Snippet.fromJson(Map<String, dynamic> json) => Snippet(
publishedAt: DateTime.parse(json["publishedAt"]),
channelId: json["channelId"],
title: json["title"],
description: json["description"],
thumbnails: Thumbnails.fromJson(json["thumbnails"]),
channelTitle: json["channelTitle"],
liveBroadcastContent: json["liveBroadcastContent"],
publishTime: DateTime.parse(json["publishTime"]),
);
Map<String, dynamic> toJson() => {
"publishedAt": publishedAt.toIso8601String(),
"channelId": channelId,
"title": title,
"description": description,
"thumbnails": thumbnails.toJson(),
"channelTitle": channelTitle,
"liveBroadcastContent": liveBroadcastContent,
"publishTime": publishTime.toIso8601String(),
};
}
class Thumbnails {
Thumbnails({
required this.thumbnailsDefault,
required this.medium,
required this.high,
});
Default thumbnailsDefault;
Default medium;
Default high;
factory Thumbnails.fromJson(Map<String, dynamic> json) => Thumbnails(
thumbnailsDefault: Default.fromJson(json["default"]),
medium: Default.fromJson(json["medium"]),
high: Default.fromJson(json["high"]),
);
Map<String, dynamic> toJson() => {
"default": thumbnailsDefault.toJson(),
"medium": medium.toJson(),
"high": high.toJson(),
};
}
class Default {
Default({
required this.url,
required this.width,
required this.height,
});
String url;
int width;
int height;
factory Default.fromJson(Map<String, dynamic> json) => Default(
url: json["url"],
width: json["width"],
height: json["height"],
);
Map<String, dynamic> toJson() => {
"url": url,
"width": width,
"height": height,
};
}
class PageInfo {
PageInfo({
required this.totalResults,
required this.resultsPerPage,
});
int totalResults;
int resultsPerPage;
factory PageInfo.fromJson(Map<String, dynamic> json) => PageInfo(
totalResults: json["totalResults"],
resultsPerPage: json["resultsPerPage"],
);
Map<String, dynamic> toJson() => {
"totalResults": totalResults,
"resultsPerPage": resultsPerPage,
};
}
youtube_api_service.dart
import 'package:http/http.dart' as http;
import 'package:starcast_intros/models/youtube_search.dart';
import 'package:starcast_intros/private_keys.dart';
class YoutubeApi {
static const String youtubeAPI =
'https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=5&q=surfing&type=video&videoDefinition=standard&videoDimension=2d&videoDuration=short&videoEmbeddable=true&key=$YOUTUBE_DATA_API_KEY';
Future<YoutubeSearchVideos> fetchVideos() async {
try {
final response = await http.get(Uri.parse(youtubeAPI));
if (response.statusCode == 200) {
return youtubeSearchVideosFromJson(response.body);
}
throw Exception('Failed to fetch videos ${response.body}');
} catch (e) {
print(e);
throw Exception('Failed to fetch videos $e');
}
}
}
2. After retrieving the list of youtube video IDs from the API, render the Youtube videos like Tinder cards which can be swiped left or right.
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:starcast_intros/models/youtube_search.dart';
import 'package:starcast_intros/services/youtube_api.dart';
import 'package:tcard/tcard.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
static const HOME = 'Home';
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
late Future<YoutubeSearchVideos> futureVideos;
#override
void initState() {
super.initState();
final youtubeAPI = YoutubeApi();
futureVideos = youtubeAPI.fetchVideos();
}
#override
Widget build(BuildContext context) {
return FutureBuilder<YoutubeSearchVideos>(
future: futureVideos,
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Widget> cards = List.generate(
snapshot.data!.items.length,
(int index) {
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: snapshot.data!.items[index].id.videoId,
flags: YoutubePlayerFlags(
autoPlay: false,
mute: true,
isLive: false,
disableDragSeek: true,
loop: false,
forceHD: false,
),
);
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.0),
boxShadow: [
BoxShadow(
offset: Offset(0, 17),
blurRadius: 23.0,
spreadRadius: -13.0,
color: Colors.black54,
)
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: YoutubePlayer(
controller: _controller,
),
),
);
},
);
return TCard(
size: Size(
MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height,
),
cards: cards,
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return SpinKitDoubleBounce(
color: Theme.of(context).accentColor,
size: 75.0,
);
},
);
}
}
Please note that you would need a Youtube API key (create it using Google Console) to retrieve the list of videos. I am using the Youtube Search API. Probably, you can use the below-given JSON if you do not wanna make a request or create an API key:
{ "kind": "youtube#searchListResponse", "etag":
"E2FpjhO0gVzn8gmf9Q1VSJ72Rwk", "nextPageToken": "CAUQAA",
"regionCode": "IN", "pageInfo": {
"totalResults": 1000000,
"resultsPerPage": 5 }, "items": [
{
"kind": "youtube#searchResult",
"etag": "HmJbuO71viHMk8216TydPkfPIAg",
"id": {
"kind": "youtube#video",
"videoId": "xIspFfN3vfs"
},
"snippet": {
"publishedAt": "2020-03-06T22:13:55Z",
"channelId": "UCR03gYk1xLMV4ko8ljxTeIA",
"title": "Nick O'Bea : How to Wing surf",
"description": "Wing Surfing How to: Skills and Drills on the wing with Nick O'Bea 5'1"x26" 90 liters from supsurfmachines.com 6
meter F1 Swing in 10-12 mph 1020 AXIS ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/xIspFfN3vfs/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/xIspFfN3vfs/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/xIspFfN3vfs/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Rush Mark Rush",
"liveBroadcastContent": "none",
"publishTime": "2020-03-06T22:13:55Z"
}
},
{
"kind": "youtube#searchResult",
"etag": "PbsGbvz61v4Fpq4DwtLexeIB708",
"id": {
"kind": "youtube#video",
"videoId": "0zO26j6vNGg"
},
"snippet": {
"publishedAt": "2016-08-10T08:07:07Z",
"channelId": "UCjYiM-YLuOQN-4S0I7PfgVg",
"title": "Alison Teal: Surfing Hawaii Volcano Eruption",
"description": "Kilauea Volcano is erupting on the Big Island of Hawaii and flowing into the ocean for the first time since 2011.
Alison, a surfer and film maker, travels the world ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/0zO26j6vNGg/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/0zO26j6vNGg/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/0zO26j6vNGg/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Alison's Adventures",
"liveBroadcastContent": "none",
"publishTime": "2016-08-10T08:07:07Z"
}
},
{
"kind": "youtube#searchResult",
"etag": "Ab0zXs-KAbFMVeH4jBajBEj60yU",
"id": {
"kind": "youtube#video",
"videoId": "pPGaGZTMc_4"
},
"snippet": {
"publishedAt": "2011-12-05T17:08:27Z",
"channelId": "UChug4c-a2tUGgZ-XeEKdxZQ",
"title": "Strongbow Neon Night Surfing Bondi",
"description": "To mark the start of summer, Strongbow joined forces with legendary surfing filmmaker Jack McCoy (Endless Summer
II), Bali Strickland and Eugene Tan ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/pPGaGZTMc_4/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/pPGaGZTMc_4/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/pPGaGZTMc_4/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Surfers Village TV",
"liveBroadcastContent": "none",
"publishTime": "2011-12-05T17:08:27Z"
}
},
{
"kind": "youtube#searchResult",
"etag": "XjmemrMgMcym-3mlYs53ie_w3t4",
"id": {
"kind": "youtube#video",
"videoId": "4uwtqRBE4Kk"
},
"snippet": {
"publishedAt": "2010-08-13T02:10:28Z",
"channelId": "UCTYHNSWYy4jCSCj1Q1Fq0ew",
"title": "Andy Irons - i surf because short film",
"description": "Andy Irons is one of the world's greatest ever surfers. A 3 times world champion made famous by his epic battles with
Kelly Slater. But outside all the victories ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/4uwtqRBE4Kk/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/4uwtqRBE4Kk/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/4uwtqRBE4Kk/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Billabong",
"liveBroadcastContent": "none",
"publishTime": "2010-08-13T02:10:28Z"
}
},
{
"kind": "youtube#searchResult",
"etag": "FZQyT7mq6dN1LX4M5RjXzVJxrtQ",
"id": {
"kind": "youtube#video",
"videoId": "kGvs0Nv5zJo"
},
"snippet": {
"publishedAt": "2013-11-15T09:31:05Z",
"channelId": "UCNSfJB-VQeHpv5ThtV1VtBA",
"title": "Wave cinematographer captures surfer's last wave",
"description": "On Wednesday morning, well known Wave Cinematographer Larry Haynes was filming those big sets from the
shore, and was rolling on Kirk Passmore as the ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/kGvs0Nv5zJo/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/kGvs0Nv5zJo/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/kGvs0Nv5zJo/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "KITV",
"liveBroadcastContent": "none",
"publishTime": "2013-11-15T09:31:05Z"
}
} ] }
Once the card is stacked with different videos, I swipe the card at the top. As soon as I swipe, the video in the 1st card appears in the card beneath (2nd card). I expected the 2nd video to play in the 2nd card as all the video IDs are different.
If I just drag a little and hold it, I can see the thumbnail of the 2nd video in the 2nd card. But, as soon as I swipe right, the video in the 2nd card (2nd video) gets replaced with the video in the 1st card (1st video).
This repeats until the last card.
Any help to crack this would be much appreciated. Thanks in anticipation.
Cheers.
Add a unique key to each of the YouTube cards, You could use the YouTube ID as a key
When to Use Keys