Flutter - Run Async Function for Each Listview Item

只谈情不闲聊 提交于 2020-05-15 19:02:54

问题


I have a list of locations I retrieve and display in a Listview Builder.

Each location has a latitude and longitude value.

Am now trying to include a "distance" field to the Listview using the GeoLocator Plugin (https://pub.dartlang.org/packages/geolocator) - by having a "Find Nearest" button that gets the user location, then calculates the distance using the user's lat/lon and each location's lat/lon.

Since the "GeoLocator Calculate Distance Method" is asynchronous, I can't insert Geolocator().distanceBetween(userLat, userLon, storeLat, storeLon) directly into the widget.

QUESTION: So how can I do it such that, when the user clicks on the button "Find Nearest", each Listview item is passed through the getDistance method and returns a result?

Simplified Code:

Future<List> getdata() async {
final response = await http.get(getStoreLocations);
return json.decode(response.body);
}


@override
Widget build(BuildContext context) {
return new Scaffold(
  appBar: new AppBar(title: new Text("Location"),),
  body: new FutureBuilder<List>(
    future: getdata(),
    builder: (context, snapshot) {
      if (snapshot.hasError) print(snapshot.error);
      return snapshot.hasData
          ? new BrowseStoreLocation(
          list: snapshot.data,)
          : new Center(
        child: new CircularProgressIndicator(),
      );
    },
  ),
);
}
}

GeoLocator Get User location Method:

getLocation () async {
Position position = await Geolocator().getCurrentPosition(LocationAccuracy.best);
userLat = position.latitude;
userLon = position.longitude;
setState(() {

});
}

GeoLocator Calculate Distance Method:

getDistance()async {
double distanceInMeters = await Geolocator().distanceBetween(userLat, 
userLon, storeLat, storeLon);
distance = distanceInMeters/1000;
}

I have tried experimenting by setting variables. The print displayed the storeLat and storeLon values for all items, but only the last listitem was calculated and returned.

String storeLat = "";
String storeLon = "";
getDistance(storeLat,storeLon)async {
double distanceInMeters = await Geolocator().distanceBetween(userLat, userLon, double.parse(storeLat), double.parse(storeLon));
distance = distanceInMeters/1000;
setState(() {
});
}

new ListView.builder(
itemCount: widget.list == null ? 0 : widget.list.length,
itemBuilder: (context, i) {
storeLat = widget.list[i]['latitude'];
storeLon = widget.list[i]['longitude'];
print(storeLon+storeLat);
return Container(
child: Column(
children: <Widget>[
new Text(distance.toString())
],
),

回答1:


You have to use FutureBuilder for this purpose inside your ListView.builder and then have to call your method getDistance inside that.

ListView.builder(
  itemCount: locationsList.length,
  itemBuilder: (context, position) {
    final current = locationsList[position];
    return FutureBuilder<String>(
      future: getDistance(current.latitude, current.longitude)
                   .then((location) => location.toString()),
      builder: (context, snapshot) {
        return Container(
          child: Column(
            children: <Widget>[new Text(snapshot.data)],
          ),
        );
     });
});


来源:https://stackoverflow.com/questions/52359405/flutter-run-async-function-for-each-listview-item

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!