Reputation: 407
class Restaurants with ChangeNotifier {
List<Restaurant> _restaurants = [];
List<Restaurant> get getRestaurants1 {
return [..._restaurants];
}
Future<void> fetchAndSetRestaurants() async {
List<Restaurant> tempRestaurants = [];
try {
List<RestaurantItems> restItems = [];
List<Reviews> reviews = [];
await FirebaseFirestore.instance.collection('restaurants').get().then(
(restaurants) => restaurants.docs.forEach(
(restaurantData) async {
if (restaurantData.id == null) {
print('no id error');
}
print('restaurant Id:');
print(restaurantData.id);
final Map<String, dynamic> restaurant = restaurantData.data();
print(restaurant);
await FirebaseFirestore.instance // Restaurant Items
.collection('restaurants')
.doc(restaurantData.id)
.collection('restaurantItems')
.get()
.then(
(firestoreRestaurantItems) {
firestoreRestaurantItems.docs.forEach(
(restItemData) {
print(restItemData.data());
final Map<String, dynamic> restItem =
restItemData.data();
print('before:');
print(restItem['price'].runtimeType);
final RestaurantItems newRestaurantItem =
RestaurantItems(
id: restItemData.id,
description: restItem['description'],
//imageUrl: restItem['imageUrl'],
isVeg: restItem['isVeg'],
name: restItem['name'],
price: restItem['price'].toDouble(),
quantity: restItem['quantity'],
);
print('After:');
print(newRestaurantItem.name);
if (newRestaurantItem == null) {
print('fail');
}
restItems.add(newRestaurantItem);
},
);
},
);
await FirebaseFirestore.instance // Restaurant Items
.collection('restaurants')
.doc(restaurantData.id)
.collection('reviews')
.get()
.then(
(firestorReviews) {
firestorReviews.docs.forEach(
(reviewData) {
final Map<String, dynamic> review = reviewData.data();
print('before:');
print(reviewData['text']);
final Reviews newReview = Reviews(
id: reviewData.id,
rating: review['rating'],
description: review['description'],
text: review['text']);
print('after');
print(newReview.text);
reviews.add(newReview);
},
);
},
);
final strings = List<String>.from(restaurant['cuisine']);
print(strings.runtimeType);
final newRestaurant = Restaurant(
id: restaurantData.id,
name: restaurant['name'],
description: restaurant['description'],
cuisine: List<String>.from(restaurant['cuisine']),
imageUrl: restaurant['imageUrl'],
isAvailable: restaurant['isAvailable'],
isFavourite: restaurant['isFavourite'],
pickupTime: restaurant['pickupTime'].toDate(),
stars: restaurant['stars'].toDouble(),
location: Location(
address: restaurant['location']['address'],
city: restaurant['location']['city'],
latitude: restaurant['location']['latitude'],
longitude: restaurant['location']['longitude'],
zipcode: restaurant['location']['zipcode'],
locality: restaurant['location']['locality'],
),
items: restItems,
reviews: reviews,
);
print(newRestaurant.name);
tempRestaurants.add(newRestaurant);
print('temp:${tempRestaurants.length}');
_restaurants.add(newRestaurant);
// print('final:${_restaurants.length}');
},
),
);
print('_restaurants: ${_restaurants[0].imageUrl}');
notifyListeners();
} catch (error) {
print('error in fetchAndSetRestaurants');
throw error;
}
}
}
I am trying to retrieve restaurant data from firestore but I when I add a new restaurant item to my main List (_restaurants), it gives me the following error:
flutter: error in fetchAndSetRestaurants [VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: RangeError (index): Invalid value: Valid value range is empty: 0
The _restaurants variable seems to be empty even after adding newRestaurant in it.
Upvotes: 4
Views: 127
Reputation: 772
You should use the async-await construct because you are trying to retrieve an item while the data is still fetching.
https://dart.dev/codelabs/async-await
Like that:
final restaurants = await FirebaseFirestore.instance.collection('restaurants').get();
for (final restaurant in restaurants.docs) {
final items = FirebaseFirestore.instance.collection('restaurants')
.doc(restaurant.id)
.collection('restaurantItems')
.get();
.......
}
and then
if (_restaurants.isNotEmpty) {
print('_restaurants: ${_restaurants[0].imageUrl}');
}
notifyListeners();
and two important things:
This construction is bad
I believe it is necessary to split the methods to request data from FireStore, like that
Hope it helps :)
Upvotes: 2