Issue
I am trying to fetch the api by using flutter_bloc
library pattern and i successfully able to get the data but problem is at below i have mention the json
data the first two elements has an empty []
array in restaurant_branch
and last (third) element has the data in restaurant_branch
which results a null point exception of ("RangeError (index): Invalid value: Valid value range is empty: 0") in HomePage.dart
( in Text widget) code. So how to prevent this issue.
json data
{
"message": "restaurants returned",
"data": [
{
"id": 40,
"name": "Arnulfo",
"aboutUs": "Voluptate omnis consequatur saepe doloribus tempore quia error. Praesentium esse blanditiis illo eos qui et deserunt rerum. Velit provident aliquam eveniet qui corporis. Culpa molestiae incidunt eaque unde id tempore. Tenetur ducimus amet hic sunt et.",
"phoneNumber": 58432,
"address": "70990 Stark Streets",
"latitude": "73.6105",
"longitude": "-95.9985",
"image": "https://cdn.fakercloud.com/avatars/matthewkay__128.jpg",
"countryCode": "VE ",
"restaurantRegisterDocument": "Est qui voluptatem.",
"isDeleted": false,
"createdAt": "2021-09-04T20:24:06.310Z",
"updatedAt": "2021-09-04T20:24:06.310Z",
"restaurantTypeId": 1,
"categoryId": 1,
"userId": 3,
"user": {
"id": 3,
"firstName": "Marisa",
"lastName": "Mills",
"email": "Darrick_Reichert94@gmail.com",
"phoneNumber": "90428",
"address": "870 Guadalupe River",
"gender": "female",
"language": "ar",
"createdAt": "2021-09-04T20:14:05.939Z",
"updatedAt": "2021-09-04T20:14:05.939Z"
},
"restaurant_branch": []
},
{
"id": 39,
"name": "Maynard",
"aboutUs": "Sunt veniam numquam perferendis consequatur. Accusantium mollitia nemo odit nihil alias dolor. Voluptatibus officia consectetur nihil. Voluptas eligendi aliquam.",
"phoneNumber": 93756,
"address": "38743 Freda Green",
"latitude": "-50.3143",
"longitude": "114.4596",
"image": "https://cdn.fakercloud.com/avatars/omnizya_128.jpg",
"countryCode": "PH ",
"restaurantRegisterDocument": "Voluptatem et expedita rerum eos eaque nihil et culpa.",
"isDeleted": false,
"createdAt": "2021-09-04T20:24:06.309Z",
"updatedAt": "2021-09-04T20:24:06.309Z",
"restaurantTypeId": 1,
"categoryId": 4,
"userId": 6,
"user": {
"id": 6,
"firstName": "Layne",
"lastName": "Turcotte",
"email": "Jayson_Rice@yahoo.com",
"phoneNumber": "98802",
"address": "659 Trudie Keys",
"gender": "male",
"language": "ar",
"createdAt": "2021-09-04T20:14:05.939Z",
"updatedAt": "2021-09-04T20:14:05.939Z"
},
"restaurant_branch": []
},
{
"id": 10,
"name": "Kaden",
"aboutUs": "Et dolore cumque et iusto vel qui iste facere. Quia sed minima. Porro eos inventore qui voluptas animi voluptates fuga commodi magnam. Voluptas eligendi sunt et fugiat repudiandae asperiores maxime sit. Impedit exercitationem laudantium error autem modi voluptas et. Vitae ut non voluptatem culpa eos quae occaecati.",
"phoneNumber": 94005,
"address": "920 Sawayn Street",
"latitude": "-69.1354",
"longitude": "-176.2695",
"image": "https://cdn.fakercloud.com/avatars/daniloc_128.jpg",
"countryCode": "PW ",
"restaurantRegisterDocument": "Fugiat ut autem et voluptates aut quisquam distinctio qui aut.",
"isDeleted": true,
"createdAt": "2021-09-04T20:14:06.352Z",
"updatedAt": "2021-09-04T20:14:06.352Z",
"restaurantTypeId": 6,
"categoryId": 3,
"userId": 4,
"user": {
"id": 4,
"firstName": "Santiago",
"lastName": "Kling",
"email": "Yoshiko.Block@yahoo.com",
"phoneNumber": "4436",
"address": "809 Earlene Square",
"gender": "female",
"language": "ar",
"createdAt": "2021-09-04T20:14:05.939Z",
"updatedAt": "2021-09-04T20:14:05.939Z"
},
"restaurant_branch": [
{
"id": 4,
"name": "Audreanne",
"description": "Kreiger",
"email": "Waylon.Osinski@yahoo.com",
"phoneNumber": 95645,
"address": "91601 Clifford Bypass",
"country_code": "SM ",
"image": "https://cdn.fakercloud.com/avatars/nicolasfolliot_128.jpg",
"latitude": "-42.0925",
"longitude": "-111.4455",
"workingHours": "Carolina AI Fresh",
"workingDays": "Friday",
"offDays": "Thursday",
"locationAddress": "802 Hoppe Ranch",
"locationCity": "Diamond Bar",
"status": 2,
"hasParking": true,
"instruction": "Bogan",
"isActive": true,
"isDeleted": false,
"createdAt": "2021-09-04T20:14:07.204Z",
"updatedAt": "2021-09-04T20:14:07.204Z",
"restaurantId": 10,
"cityId": 6,
"districtId": 1,
"feedbacks": [
{
"id": 39,
"comment": "International Communications Officer",
"star": 3,
"createdAt": "2021-09-04T20:24:07.433Z",
"updatedAt": "2021-09-04T20:24:07.433Z",
"customerId": 1,
"restaurantBranchId": 4
}
]
},
]
}
RecommendedForYouModel
class RecommendedForYouDataRestaurantBranchFeedbacks {
int? id;
String? comment;
int? star;
String? createdAt;
String? updatedAt;
int? customerId;
int? restaurantBranchId;
RecommendedForYouDataRestaurantBranchFeedbacks({
this.id,
this.comment,
this.star,
this.createdAt,
this.updatedAt,
this.customerId,
this.restaurantBranchId,
});
RecommendedForYouDataRestaurantBranchFeedbacks.fromJson(
Map<String, dynamic> json) {
id = json["id"]?.toInt();
comment = json["comment"]?.toString();
star = json["star"]?.toInt();
createdAt = json["createdAt"]?.toString();
updatedAt = json["updatedAt"]?.toString();
customerId = json["customerId"]?.toInt();
restaurantBranchId = json["restaurantBranchId"]?.toInt();
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data["id"] = id;
data["comment"] = comment;
data["star"] = star;
data["createdAt"] = createdAt;
data["updatedAt"] = updatedAt;
data["customerId"] = customerId;
data["restaurantBranchId"] = restaurantBranchId;
return data;
}
}
class RecommendedForYouDataRestaurantBranch {
int? id;
String? name;
String? description;
String? email;
int? phoneNumber;
String? address;
String? countryCode;
String? image;
String? latitude;
String? longitude;
String? workingHours;
String? workingDays;
String? offDays;
String? locationAddress;
String? locationCity;
int? status;
bool? hasParking;
String? instruction;
bool? isActive;
bool? isDeleted;
String? createdAt;
String? updatedAt;
int? restaurantId;
int? cityId;
int? districtId;
List<RecommendedForYouDataRestaurantBranchFeedbacks?>? feedbacks;
RecommendedForYouDataRestaurantBranch({
this.id,
this.name,
this.description,
this.email,
this.phoneNumber,
this.address,
this.countryCode,
this.image,
this.latitude,
this.longitude,
this.workingHours,
this.workingDays,
this.offDays,
this.locationAddress,
this.locationCity,
this.status,
this.hasParking,
this.instruction,
this.isActive,
this.isDeleted,
this.createdAt,
this.updatedAt,
this.restaurantId,
this.cityId,
this.districtId,
this.feedbacks,
});
RecommendedForYouDataRestaurantBranch.fromJson(Map<String, dynamic> json) {
id = json["id"]?.toInt();
name = json["name"]?.toString();
description = json["description"]?.toString();
email = json["email"]?.toString();
phoneNumber = json["phoneNumber"]?.toInt();
address = json["address"]?.toString();
countryCode = json["country_code"]?.toString();
image = json["image"]?.toString();
latitude = json["latitude"]?.toString();
longitude = json["longitude"]?.toString();
workingHours = json["workingHours"]?.toString();
workingDays = json["workingDays"]?.toString();
offDays = json["offDays"]?.toString();
locationAddress = json["locationAddress"]?.toString();
locationCity = json["locationCity"]?.toString();
status = json["status"]?.toInt();
hasParking = json["hasParking"];
instruction = json["instruction"]?.toString();
isActive = json["isActive"];
isDeleted = json["isDeleted"];
createdAt = json["createdAt"]?.toString();
updatedAt = json["updatedAt"]?.toString();
restaurantId = json["restaurantId"]?.toInt();
cityId = json["cityId"]?.toInt();
districtId = json["districtId"]?.toInt();
if (json["feedbacks"] != null) {
final v = json["feedbacks"];
final arr0 = <RecommendedForYouDataRestaurantBranchFeedbacks>[];
v.forEach((v) {
arr0.add(RecommendedForYouDataRestaurantBranchFeedbacks.fromJson(v));
});
feedbacks = arr0;
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data["id"] = id;
data["name"] = name;
data["description"] = description;
data["email"] = email;
data["phoneNumber"] = phoneNumber;
data["address"] = address;
data["country_code"] = countryCode;
data["image"] = image;
data["latitude"] = latitude;
data["longitude"] = longitude;
data["workingHours"] = workingHours;
data["workingDays"] = workingDays;
data["offDays"] = offDays;
data["locationAddress"] = locationAddress;
data["locationCity"] = locationCity;
data["status"] = status;
data["hasParking"] = hasParking;
data["instruction"] = instruction;
data["isActive"] = isActive;
data["isDeleted"] = isDeleted;
data["createdAt"] = createdAt;
data["updatedAt"] = updatedAt;
data["restaurantId"] = restaurantId;
data["cityId"] = cityId;
data["districtId"] = districtId;
if (feedbacks != null) {
final v = feedbacks;
final arr0 = [];
v!.forEach((v) {
arr0.add(v!.toJson());
});
data["feedbacks"] = arr0;
}
return data;
}
}
class RecommendedForYouDataUser {
int? id;
String? firstName;
String? lastName;
String? email;
String? phoneNumber;
String? address;
String? gender;
String? language;
String? createdAt;
String? updatedAt;
RecommendedForYouDataUser({
this.id,
this.firstName,
this.lastName,
this.email,
this.phoneNumber,
this.address,
this.gender,
this.language,
this.createdAt,
this.updatedAt,
});
RecommendedForYouDataUser.fromJson(Map<String, dynamic> json) {
id = json["id"]?.toInt();
firstName = json["firstName"]?.toString();
lastName = json["lastName"]?.toString();
email = json["email"]?.toString();
phoneNumber = json["phoneNumber"]?.toString();
address = json["address"]?.toString();
gender = json["gender"]?.toString();
language = json["language"]?.toString();
createdAt = json["createdAt"]?.toString();
updatedAt = json["updatedAt"]?.toString();
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data["id"] = id;
data["firstName"] = firstName;
data["lastName"] = lastName;
data["email"] = email;
data["phoneNumber"] = phoneNumber;
data["address"] = address;
data["gender"] = gender;
data["language"] = language;
data["createdAt"] = createdAt;
data["updatedAt"] = updatedAt;
return data;
}
}
class RecommendedForYouData {
int? id;
String? name;
String? aboutUs;
int? phoneNumber;
String? address;
String? latitude;
String? longitude;
String? image;
String? countryCode;
String? restaurantRegisterDocument;
bool? isDeleted;
String? createdAt;
String? updatedAt;
int? restaurantTypeId;
int? categoryId;
int? userId;
RecommendedForYouDataUser? user;
List<RecommendedForYouDataRestaurantBranch?>? restaurantBranch;
RecommendedForYouData({
this.id,
this.name,
this.aboutUs,
this.phoneNumber,
this.address,
this.latitude,
this.longitude,
this.image,
this.countryCode,
this.restaurantRegisterDocument,
this.isDeleted,
this.createdAt,
this.updatedAt,
this.restaurantTypeId,
this.categoryId,
this.userId,
this.user,
this.restaurantBranch,
});
RecommendedForYouData.fromJson(Map<String, dynamic> json) {
id = json["id"]?.toInt();
name = json["name"]?.toString();
aboutUs = json["aboutUs"]?.toString();
phoneNumber = json["phoneNumber"]?.toInt();
address = json["address"]?.toString();
latitude = json["latitude"]?.toString();
longitude = json["longitude"]?.toString();
image = json["image"]?.toString();
countryCode = json["countryCode"]?.toString();
restaurantRegisterDocument = json["restaurantRegisterDocument"]?.toString();
isDeleted = json["isDeleted"];
createdAt = json["createdAt"]?.toString();
updatedAt = json["updatedAt"]?.toString();
restaurantTypeId = json["restaurantTypeId"]?.toInt();
categoryId = json["categoryId"]?.toInt();
userId = json["userId"]?.toInt();
user = (json["user"] != null)
? RecommendedForYouDataUser.fromJson(json["user"])
: null;
if (json["restaurant_branch"] != null) {
final v = json["restaurant_branch"];
final arr0 = <RecommendedForYouDataRestaurantBranch>[];
v.forEach((v) {
arr0.add(RecommendedForYouDataRestaurantBranch.fromJson(v));
});
restaurantBranch = arr0;
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data["id"] = id;
data["name"] = name;
data["aboutUs"] = aboutUs;
data["phoneNumber"] = phoneNumber;
data["address"] = address;
data["latitude"] = latitude;
data["longitude"] = longitude;
data["image"] = image;
data["countryCode"] = countryCode;
data["restaurantRegisterDocument"] = restaurantRegisterDocument;
data["isDeleted"] = isDeleted;
data["createdAt"] = createdAt;
data["updatedAt"] = updatedAt;
data["restaurantTypeId"] = restaurantTypeId;
data["categoryId"] = categoryId;
data["userId"] = userId;
if (user != null) {
data["user"] = user!.toJson();
}
if (restaurantBranch != null) {
final v = restaurantBranch;
final arr0 = [];
v!.forEach((v) {
arr0.add(v!.toJson());
});
data["restaurant_branch"] = arr0;
}
return data;
}
}
class RecommendedForYou {
String? message;
List<RecommendedForYouData?>? data;
RecommendedForYou({
this.message,
this.data,
});
RecommendedForYou.fromJson(Map<String, dynamic> json) {
message = json["message"]?.toString();
if (json["data"] != null) {
final v = json["data"];
final arr0 = <RecommendedForYouData>[];
v.forEach((v) {
arr0.add(RecommendedForYouData.fromJson(v));
});
this.data = arr0;
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data["message"] = message;
if (this.data != null) {
final v = this.data;
final arr0 = [];
v!.forEach((v) {
arr0.add(v!.toJson());
});
data["data"] = arr0;
}
return data;
}
}
HomePage.dart
Container(
child: Padding(
padding:
const EdgeInsets.only(top: 20.0, left: 20.0, right: 20.0),
child: Container(
height: height,
child: BlocBuilder<RecommendedBloc, RecommendedState>(
builder: (context, state) {
if (state is LoadingRecommendedState) {
return Center(
child: PlatformCircularProgressIndicator());
} else if (state is LoadedRecommendedForYouState) {
return buildRecommendationRestaurant(state.data);
} else if (state is ErrorRecommendedState) {
return Center(child: Text(state.message));
}
return Container();
}),
),
),
),
Widget buildRecommendationRestaurant(List<RecommendedForYouData> data) {
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
child: Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Card(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.only(top: 5.0, right: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.near_me,
size: 10.0,
),
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Text(
'5km',
style: TextStyle(fontSize: 10.0),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: CachedNetworkImage(
imageUrl: data[index].image!,
fit: BoxFit.cover,
placeholder: (context, url) => Center(
child:
PlatformCircularProgressIndicator()),
errorWidget: (context, url, error) =>
Icon(Icons.error),
height:
MediaQuery.of(context).size.width * 0.18,
width:
MediaQuery.of(context).size.width * 0.18,
),
),
Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 35.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
data[index].name!,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
Row(
children: [
Text(
'4.5',
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.w500),
),
Text(
'(${data[index].restaurantBranch![index]!.feedbacks!.length.toString()} RATING)', //Here on this line getting null because first element is []
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.w500),
)
],
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Row(
children: [
ImageIcon(
AssetImage(
'images/food-serving.png'),
size: 15.0,
),
Text(
'Italian Food - Steake',
style: TextStyle(fontSize: 12.0),
)
],
),
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Row(
children: [
Icon(
Icons.location_on_outlined,
size: 12.0,
color: TuxedoColor.greyColor,
),
Text(
'Riyadh',
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w600),
)
],
),
)
],
),
),
],
),
),
],
),
)),
),
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => DetailsPage(
id: data[index].id!,
)));
},
);
});
}
Solution
You are using your parent listView’s index
variable for restaurant_branch
array also. Since restaurant_branch
is a different array you should use a nested ListView if you want to effectively display branches on the layout. In you case if every restaurant
do not have multiple branches you can use it like this
.......
Row(
children: [
Text(
'4.5',
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.w500),
),
Text(
'(${data[index].restaurantBranch![0]!.feedbacks!.length.toString()} RATING)', //Here on this line getting null because first element is []
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.w500),
)
],
),
......
Answered By – HasilT
Answer Checked By – Pedro (FlutterFixes Volunteer)