I've been trying to sort a list of objects, Here's there code:-
class Locations {
final GeoPoint location;
Locations({this.location});
}
class LocationCard extends StatefulWidget {
final int index;
LocationCard({this.index});
@override
_LocationCardState createState() => _LocationCardState();
}
class _LocationCardState extends State<LocationCard> {
@override
Widget build(BuildContext context) {
final List<Locations> locationlist = [
Locations(location: GeoPoint(1, 2)),
Locations(location: GeoPoint(2, 2)),
Locations(location: GeoPoint(3, 2)),
Locations(location: GeoPoint(4, 1))
]; //list to be sorted
GeoPoint mylocation = GeoPoint(2, 2);
double distance;
var userindex;
List sorted = [];
//sort locationlist here
for (var i = 0; i < sorted.length; i++) {
if (sorted[i].location == mylocation) {
userindex = sorted.indexOf(locationlist[i]);
}
}//gets user's index in list
futureconvert() async {
distance = await Geolocator().distanceBetween(
sorted[userindex].location.longitude,
sorted[userindex].location.latitude,
sorted[widget.index].location.longitude,
sorted[widget.index].location.latitude) /
1000;
return distance;
}
return Container(
child: Card(
child: Center(
child: FutureBuilder(
future: futureconvert(),
builder: (context, snapshot) {
return Text(distance.toString());
}),
),
),
);
}
}
class LocationList extends StatefulWidget {
@override
_LocationListState createState() => _LocationListState();
}
class _LocationListState extends State<LocationList> {
@override
Widget build(BuildContext context) {
final List<Locations> locationlist = [
Locations(location: GeoPoint(1, 2)),
Locations(location: GeoPoint(2, 2)),
Locations(location: GeoPoint(3, 2)),
Locations(location: GeoPoint(4, 1))
]; //list to be sorted
GeoPoint mylocation = GeoPoint(2, 2);//current user location
List sorted = [];
//sort locationlist here
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: sorted.length,
itemBuilder: (context, index) {
return LocationCard(index: index);
});
}
}
I need a function that sorts locationlist
base on proximity to mylocation
.I tried sorting using value returned by this function
distancef(var x, var y) async {
return await Geolocator().distanceBetween(
locationlist[userindex].location.longitude,
locationlist[userindex].location.latitude,
x,
y);
}
But it look's like I have to write my own custom sorting function because I have a future value in return.
How do I do this?
Since we need the distance anyway, we can map each location to distance first. Then sort them by distance. A FutureBuilder can be used to build the ListView.
class LocationList extends StatefulWidget {
@override
_LocationListState createState() => _LocationListState();
}
class _LocationListState extends State<LocationList> {
@override
Widget build(BuildContext context) {
// location list and mylocation
Future<int> distanceFromMyLocation(Locations location) async {
int distance = await Geolocator().distanceBetween(
mylocation.location.longitude,
mylocation.location.latitude,
location.location.longitude,
location.location.latitude) /
1000;
return distance;
}
// Return a list of location and corresponding distance from user
Future<List<Map<String, dynamic>>> sortByDistance(List<Locations> locationlist) async {
// make this an empty list by intializing with []
List<Map<String, dynamic>> locationListWithDistance = [];
// associate location with distance
for(var location in locationlist) {
int distance = await distanceFromMyLocation(location);
locationListWithDistance.add({
'location': location,
'distance': distance,
});
}
// sort by distance
locationListWithDistance.sort((a, b) {
int d1 = a['distance'];
int d2 = b['distance'];
if (d1 > d2) return 1;
else if (d1 < d2) return -1;
else return 0;
});
return locationListWithDistance;
}
return FutureBuilder(
future: sortByDistance(locationlist),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
var sorted = snapshot.data as List<Map<String, dynamic>>;
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: sorted.length,
itemBuilder: (context, index) {
return LocationCard(sorted[index]);
});
},
);
}
}
class LocationCard extends StatelessWidget {
final Map<String, dynamic> locationAndDistance;
LocationCard({this.locationAndDistance});
@override
Widget build(BuildContext context) {
return Container(
child: Card(
child: Center(
// location can be accessed by locationAndDistance['location']
// distance can be accessed by locationAndDistance['distance']
child: Text(locationAndDistance['distance'].toString());
),
),
);
}
}