未来建设者不断更新
Future builder Constantly Updates
我正在使用 Future 构建器从快照中获取数据并将该数据过滤到另一个创建标记的 Future 函数中。我通过过滤所有餐厅的位置得到结果,但是该功能不断更新并且数据只是闪烁。
编辑 2:JSON 数据
{ restaurant:[ {
"id": 4,
"restaurant_name": "Good Chemistry",
"phone": "1231231234",
"street_address": "2 Penn Plaza",
"restaurant_logo": "https://restaurants.s3.amazonaws.com/restaurant_logo/GOODCHEM-3-web_99314.jpg",
"restaurant_photo": "https://restaurants.s3.amazonaws.com/restaurant_photo/GOODCHEM-3-web_99314.jpg",
"city": "NY",
"state": "New York",
"zip_Code": 10010,
"lat": 40.8931283,
"lng": -73.8205375,
"latlng": "(40.7770112244898, -74.2110798163265)",
"opening_hours": [
{
"day_of_week": "Tuesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Wednesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Thursday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Friday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Saturday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Sunday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": 7,
"opening_time": "08:00:00",
"closing_time": "22:00:00"
}
],
"ratings": 4.1
},
{
"id": 3,
"restaurant_name": "The Farmacy",
"phone": "1231231234",
"street_address": "11 Penn Plaza",
"restaurant_logo": "https://restaurants.s3.amazonaws.com/restaurant_logo/farma.jpg",
"restaurant_photo": "https://restaurants.s3.amazonaws.com/restaurant_photo/farma.jpg",
"city": "NY",
"state": "New York",
"zip_Code": 10010,
"lat": 40.8931283,
"lng": -73.8205375,
"latlng": "(40.7770112244898, -74.2110798163265)",
"opening_hours": [
{
"day_of_week": "Tuesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Wednesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Thursday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Friday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Saturday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Sunday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": 7,
"opening_time": "08:00:00",
"closing_time": "22:00:00"
}
],
"ratings": 4.7
},
{
"id": 2,
"restaurant_name": "Hoboken Smokin",
"phone": "123-123-1234",
"street_address": "11 Penn Plaza",
"restaurant_logo": "https://restaurants.s3.amazonaws.com/restaurant_logo/urban-restaurant-web-1024x640.jpg",
"restaurant_photo": "https://restaurants.s3.amazonaws.com/restaurant_photo/urban-restaurant-web-1024x640.jpg",
"city": "NY",
"state": "New York",
"zip_Code": 10010,
"lat": 40.8931283,
"lng": -73.8205375,
"latlng": "(40.7770112244898, -74.2110798163265)",
"opening_hours": [
{
"day_of_week": "Tuesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Wednesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Thursday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Friday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Saturday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Sunday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": 7,
"opening_time": "08:00:00",
"closing_time": "22:00:00"
}
],
"ratings": 3.5
},
{
"id": 1,
"restaurant_name": "The Bakeree",
"phone": "1231231234",
"street_address": "433 5th Ave",
"restaurant_logo": "https://restaurants.s3.amazonaws.com/restaurant_logo/restaurantimage.jpeg",
"restaurant_photo": "https://restaurants.s3.amazonaws.com/restaurant_photo/restaurantimage.jpeg",
"city": "NY",
"state": "New York",
"zip_Code": 10016,
"lat": 40.7512061,
"lng": -73.9822721,
"latlng": "(40.7770112244898, -74.2110798163265)",
"opening_hours": [
{
"day_of_week": "Tuesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Wednesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Thursday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Friday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Saturday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Sunday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": 7,
"opening_time": "08:00:00",
"closing_time": "22:00:00"
}
],
"ratings": 4.6
}
]
}
编辑 1:_setRestaurant 函数
Future getRestaurants() async {
var url = 'http://yellows-1929.herokuapp.com/api/customer/restaurant/';
var response = await http.get(url);
var responseData = json.decode(response.body);
Restaurants _restaurant = Restaurants.fromJSON(responseData);
return _restaurant.restaurant;
}
Filter Location function
<!-- begin snippet: js hide: false console: true babel: false -->
获取数据并调用函数 filterMarker 的未来构建器:
Widget _buildRestaurants() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
FutureBuilder(
future: _setRestaurants,
builder: (context, AsyncSnapshot snapshot) {
var restaurants = snapshot.data;
recRestaurants = snapshot.data;
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
} else {
filterMarker(restaurants, 20);
return Column(
children: <Widget>[
_makeRestaurants(restaurants),
_buildCoupon(),
_buildVendors(filteredVenues)
],
);
}
})
]));
}
过滤器不断更新和打印
flutter: the lat is 41.722068434324785 and the long is -74.34910777767849
flutter: There are 1 _filteredMarkers
flutter: There are 0 _filteredMarkers
flutter: There are 0 _filteredMarkers
flutter: There are 1 _filteredMarkers
flutter: There are 1 _filteredMarkers
flutter: There are 1 _filteredMarkers
flutter: There are 0 _filteredMarkers
flutter: There are 0 _filteredMarkers
flutter: There are 1 _filteredMarkers
如果没有完整的代码片段,很难判断发生了什么 - 如果您创建了一个小的工作示例来显示发生了什么,那会更有帮助。
不过,我相信有几件事可能会有所帮助。
尽可能停止构建具有函数的小部件。如果它复杂到需要一个函数来构建它,您很可能应该在它自己的小部件中构建它。这允许 flutter 优化不同小部件的构建以及清理代码。
不清楚 _setRestaurants
是什么,但您在 FutureBuilder 中引用了它。立即执行此操作是 _setRestaurants
成为 Future,并且仅在 完成新服务器请求时 更改它。将 _setRestaurants
对象视为小部件状态的一部分,并假设当它更改时小部件将被重建。所以这看起来像:
Future<Restaurants> _setRestaurants;
void initState() {
super.initState();
_setRestaurants = _getRestaurants();
}
void updateRestaurants() {
setState(() {
_setRestaurants = _getRestaurants();
});
}
请注意,我实际上并不完全推荐这样做,这只是为了演示 OP 可能做错了什么。
您可能不应该在客户端过滤数据。想想规模——如果你有 50 家餐厅,我想这是可持续的,但如果你有 1000 家,你就不能每次都要求。您应该改为向获取请求添加参数并在服务器上进行过滤。
从 "displaying the restaurants on the screen" 部分中分离出 "retrieving information from server and filtering" 部分是有意义的。这样你就可以分离关注点,你可以独立测试服务器部分和 UI 部分,它会更健壮。有很多不同的方法可以解决这个问题,所以我不打算在这里深入讨论,因为它超出了这个问题的范围,但请查看 MVVM 或查看 Flutter State Management page 上的一些链接.您还可以使用 StreamBuilder 和流而不是 futurebuilder,因为这样可以在每次更改数据时(即更改过滤器时)显示更新的结果。
我正在使用 Future 构建器从快照中获取数据并将该数据过滤到另一个创建标记的 Future 函数中。我通过过滤所有餐厅的位置得到结果,但是该功能不断更新并且数据只是闪烁。
编辑 2:JSON 数据
{ restaurant:[ {
"id": 4,
"restaurant_name": "Good Chemistry",
"phone": "1231231234",
"street_address": "2 Penn Plaza",
"restaurant_logo": "https://restaurants.s3.amazonaws.com/restaurant_logo/GOODCHEM-3-web_99314.jpg",
"restaurant_photo": "https://restaurants.s3.amazonaws.com/restaurant_photo/GOODCHEM-3-web_99314.jpg",
"city": "NY",
"state": "New York",
"zip_Code": 10010,
"lat": 40.8931283,
"lng": -73.8205375,
"latlng": "(40.7770112244898, -74.2110798163265)",
"opening_hours": [
{
"day_of_week": "Tuesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Wednesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Thursday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Friday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Saturday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Sunday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": 7,
"opening_time": "08:00:00",
"closing_time": "22:00:00"
}
],
"ratings": 4.1
},
{
"id": 3,
"restaurant_name": "The Farmacy",
"phone": "1231231234",
"street_address": "11 Penn Plaza",
"restaurant_logo": "https://restaurants.s3.amazonaws.com/restaurant_logo/farma.jpg",
"restaurant_photo": "https://restaurants.s3.amazonaws.com/restaurant_photo/farma.jpg",
"city": "NY",
"state": "New York",
"zip_Code": 10010,
"lat": 40.8931283,
"lng": -73.8205375,
"latlng": "(40.7770112244898, -74.2110798163265)",
"opening_hours": [
{
"day_of_week": "Tuesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Wednesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Thursday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Friday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Saturday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Sunday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": 7,
"opening_time": "08:00:00",
"closing_time": "22:00:00"
}
],
"ratings": 4.7
},
{
"id": 2,
"restaurant_name": "Hoboken Smokin",
"phone": "123-123-1234",
"street_address": "11 Penn Plaza",
"restaurant_logo": "https://restaurants.s3.amazonaws.com/restaurant_logo/urban-restaurant-web-1024x640.jpg",
"restaurant_photo": "https://restaurants.s3.amazonaws.com/restaurant_photo/urban-restaurant-web-1024x640.jpg",
"city": "NY",
"state": "New York",
"zip_Code": 10010,
"lat": 40.8931283,
"lng": -73.8205375,
"latlng": "(40.7770112244898, -74.2110798163265)",
"opening_hours": [
{
"day_of_week": "Tuesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Wednesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Thursday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Friday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Saturday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Sunday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": 7,
"opening_time": "08:00:00",
"closing_time": "22:00:00"
}
],
"ratings": 3.5
},
{
"id": 1,
"restaurant_name": "The Bakeree",
"phone": "1231231234",
"street_address": "433 5th Ave",
"restaurant_logo": "https://restaurants.s3.amazonaws.com/restaurant_logo/restaurantimage.jpeg",
"restaurant_photo": "https://restaurants.s3.amazonaws.com/restaurant_photo/restaurantimage.jpeg",
"city": "NY",
"state": "New York",
"zip_Code": 10016,
"lat": 40.7512061,
"lng": -73.9822721,
"latlng": "(40.7770112244898, -74.2110798163265)",
"opening_hours": [
{
"day_of_week": "Tuesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Wednesday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Thursday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Friday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Saturday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": "Sunday",
"opening_time": "08:00:00",
"closing_time": "22:00:00"
},
{
"day_of_week": 7,
"opening_time": "08:00:00",
"closing_time": "22:00:00"
}
],
"ratings": 4.6
}
]
}
编辑 1:_setRestaurant 函数
Future getRestaurants() async {
var url = 'http://yellows-1929.herokuapp.com/api/customer/restaurant/';
var response = await http.get(url);
var responseData = json.decode(response.body);
Restaurants _restaurant = Restaurants.fromJSON(responseData);
return _restaurant.restaurant;
}
Filter Location function
<!-- begin snippet: js hide: false console: true babel: false -->
获取数据并调用函数 filterMarker 的未来构建器:
Widget _buildRestaurants() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
FutureBuilder(
future: _setRestaurants,
builder: (context, AsyncSnapshot snapshot) {
var restaurants = snapshot.data;
recRestaurants = snapshot.data;
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
} else {
filterMarker(restaurants, 20);
return Column(
children: <Widget>[
_makeRestaurants(restaurants),
_buildCoupon(),
_buildVendors(filteredVenues)
],
);
}
})
]));
}
过滤器不断更新和打印
flutter: the lat is 41.722068434324785 and the long is -74.34910777767849
flutter: There are 1 _filteredMarkers
flutter: There are 0 _filteredMarkers
flutter: There are 0 _filteredMarkers
flutter: There are 1 _filteredMarkers
flutter: There are 1 _filteredMarkers
flutter: There are 1 _filteredMarkers
flutter: There are 0 _filteredMarkers
flutter: There are 0 _filteredMarkers
flutter: There are 1 _filteredMarkers
如果没有完整的代码片段,很难判断发生了什么 - 如果您创建了一个小的工作示例来显示发生了什么,那会更有帮助。
不过,我相信有几件事可能会有所帮助。
尽可能停止构建具有函数的小部件。如果它复杂到需要一个函数来构建它,您很可能应该在它自己的小部件中构建它。这允许 flutter 优化不同小部件的构建以及清理代码。
不清楚
_setRestaurants
是什么,但您在 FutureBuilder 中引用了它。立即执行此操作是_setRestaurants
成为 Future,并且仅在 完成新服务器请求时 更改它。将_setRestaurants
对象视为小部件状态的一部分,并假设当它更改时小部件将被重建。所以这看起来像:
Future<Restaurants> _setRestaurants;
void initState() {
super.initState();
_setRestaurants = _getRestaurants();
}
void updateRestaurants() {
setState(() {
_setRestaurants = _getRestaurants();
});
}
请注意,我实际上并不完全推荐这样做,这只是为了演示 OP 可能做错了什么。
您可能不应该在客户端过滤数据。想想规模——如果你有 50 家餐厅,我想这是可持续的,但如果你有 1000 家,你就不能每次都要求。您应该改为向获取请求添加参数并在服务器上进行过滤。
从 "displaying the restaurants on the screen" 部分中分离出 "retrieving information from server and filtering" 部分是有意义的。这样你就可以分离关注点,你可以独立测试服务器部分和 UI 部分,它会更健壮。有很多不同的方法可以解决这个问题,所以我不打算在这里深入讨论,因为它超出了这个问题的范围,但请查看 MVVM 或查看 Flutter State Management page 上的一些链接.您还可以使用 StreamBuilder 和流而不是 futurebuilder,因为这样可以在每次更改数据时(即更改过滤器时)显示更新的结果。