I am iterating through a querysnapshot getting values for which am using to compute distance. The computation formulae is working fine - tested outside the for loop. The val
This issue disturbed me for some time, but the below code worked:
Future<List> getDistances() async {
distanceList = [];
for (var i in items) {
var s;
var x = i.data()[Str.ITEM_LATITUDE].toString();
var y = i.data()[Str.ITEM_LONGITUDE].toString();
double d = distanceBetween(
double.tryParse(x) ?? usersDefaultCityLat,
double.tryParse(y) ?? usersDefaultCityLong,
usersCurrentLocationLat ??
usersHomeLocationLat ??
usersDefaultCityLat,
usersCurrentLocationLong ??
usersHomeLocationLong ??
usersDefaultCityLong);
if (d < 454) {
s = "Nearby";
}
if (d >= 454 && d < 1000) {
d = d;
s = d.toStringAsFixed(0) + " M";
}
if (d >= 1000) {
s = (d / 1000).toStringAsFixed(0) + " KM";
}
distanceList.add(s);
}
return distanceList;
}
Nevertheless, this cannot be the only way I solved the issue. The following was also done:
As is above, I used a for loop unlike the foreach which was giving nulls even with proper await sequencing to avoid evaluating a future and not a value.
The await functions returning/setting values to be used for this function were all put into another async function like below;
Future<void> setUserLocationAddress() async {
await getLocationFromLocationPackage();
await setCountryCapitalCityLatlong();
await getUserHomeAddress();
await getDistances();
}
The call at the initState was only for the function above:
@override
void initState() {
super.initState();
setUserLocationAddress();
}
The call to the firebase database to get items into a list was in duplicate - this was the main culprit: I hade the following: List items and List distanceList and all were getting the items one for display and one to get the latitudes and longitudes for calculating distances. This led to duplication in the final list.
All this distances from a list (note that the text holding the distance was wrapped in a staggered grid view which was already iterating through the items List of DocumentSnapshot while initially, I was also iterating throught another list distanceList on the Text Widget using the same index key - the really issue. Nevertheless as pointed by @jamesdlin, use of local variables where possible.
FutureBuilder(
future: getDistances(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(
distanceList.length >
index
? distanceList[index]
.toString()
: "",//THIS CHECK WAS NECESSARY AGAINST LIST LENGHTS NOT MATCHING IF ANY
style: TextStyle(
color: Colors.black,
fontSize: 12.0,
fontWeight:
FontWeight.w600),
);
} else {
return Icon(Icons
.location_searching);
}
},
),
Finally, to be honest, I had to bury my head into Flutter Future - use of await and asnyc to make sense of all this: thanks to https://dart.dev/codelabs/async-await
I hope this educates someone and will help anyone in case they run into duplicate lists in side staggered grid views (gridview/listview), and use of foreach as opposed to for loop (I cannot say for sure if the for really solved the problem, but had seen similar argument somewhere else, and am safe because, the foreach gave out nulls no matter the sequence of chained awaits. This question should be a pointer to similar questions I had raised: