我怎样才能让这个 Flutter Bloc 发送更新?
How can I have this Flutter Bloc to send updates?
我有这个 Flutter bloc,它采用 Firebase 餐厅流,根据相对于用户的位置,将根据餐厅位置仅过滤最近的餐厅。它工作正常,但如果我想查看餐厅文档中的任何更改,我必须使用 RefreshIndicator 进行刷新。我错过了什么?提前致谢。
class NearestRestaurant {
final String id;
final Restaurant restaurant;
final double distance;
NearestRestaurant({this.id, this.restaurant, this.distance});
}
class NearRestaurantBloc {
final Future<List<Restaurant>> source;
final Position userCoordinates;
final _stream = StreamController<List<Restaurant>>();
NearRestaurantBloc({
this.source,
this.userCoordinates,
}) {
List<Restaurant> resList = List<Restaurant>();
source.then((rest) {
rest.forEach((res) async {
await Geolocator().distanceBetween(
userCoordinates.latitude,
userCoordinates.longitude,
res.coordinates.latitude,
res.coordinates.longitude,
).then((distance) {
if (res.active && distance < res.deliveryRadius) {
resList.add(res);
}
});
_stream.add(resList);
});
});
}
Stream<List<Restaurant>> get stream => _stream.stream;
void dispose() {
_stream.close();
}
}
class RestaurantQuery extends StatefulWidget {
@override
_RestaurantQueryState createState() => _RestaurantQueryState();
}
class _RestaurantQueryState extends State<RestaurantQuery> {
NearRestaurantBloc bloc;
@override
Widget build(BuildContext context) {
final database = Provider.of<Database>(context, listen: true);
final session = Provider.of<Session>(context);
final userCoordinates = session.position;
bloc = NearRestaurantBloc(
source: database.patronRestaurants(),
userCoordinates: userCoordinates,
);
return StreamBuilder<List<Restaurant>>(
stream: bloc.stream,
builder: (context, snapshot) {
bool stillLoading = true;
var restaurantList = List<Restaurant>();
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.hasData && snapshot.data.length > 0) {
restaurantList = snapshot.data;
}
stillLoading = false;
}
return Scaffold(
appBar: AppBar(
title: Text(
'Restaurants near you',
style: TextStyle(color: Theme.of(context).appBarTheme.color),
),
elevation: 2.0,
),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: RefreshIndicator(
onRefresh: () async {
setState(() {
});
},
child: RestaurantList(
nearbyRestaurantsList: restaurantList,
stillLoading: stillLoading,
),
),
);
},
);
}
@override
void dispose() {
bloc.dispose();
super.dispose();
}
}
在 _RestaurantQueryState
下的 build
方法中,您将在 builder
方法之外返回 scaffold
。最初,restaurantList
为空。因此,您不生成列表。每当流更新时,您都会获取快照数据以更新 restaurantList
。
问题出在这里。即使 restaurantList
已更新,小部件 RestaurantList
也不会更新,因为它在构建器方法之外。您可以使用以下代码。在这里,我们创建了一个包含 RestaurantList
小部件的小部件。每当流更新时,小部件都会更新。
class _RestaurantQueryState extends State<RestaurantQuery> {
NearRestaurantBloc bloc;
@override
Widget build(BuildContext context) {
final database = Provider.of<Database>(context, listen: true);
final session = Provider.of<Session>(context);
final userCoordinates = session.position;
//////////////////////////////////
//initialize RestaurantList widget
//////////////////////////////////
Widget restaurantWidget = RestaurantList(
nearbyRestaurantsList: [],
stillLoading: false,
);
bloc = NearRestaurantBloc(
source: database.patronRestaurants(),
userCoordinates: userCoordinates,
);
return StreamBuilder<List<Restaurant>>(
stream: bloc.stream,
builder: (context, snapshot) {
bool stillLoading = true;
var restaurantList = List<Restaurant>();
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.hasData && snapshot.data.length > 0) {
restaurantList = snapshot.data;
/////////////////////////////
//update the restaurant widget
//////////////////////////////
restaurantWidget = RestaurantList(
nearbyRestaurantsList: restaurantList,
stillLoading: stillLoading,
);
}
stillLoading = false;
}
return Scaffold(
appBar: AppBar(
title: Text(
'Restaurants near you',
style: TextStyle(color: Theme.of(context).appBarTheme.color),
),
elevation: 2.0,
),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
///////////////////////////
//use the restaurant Widget
///////////////////////////
body: restaurantWidget,
),
);
},
);
}
我的错误。我在听未来而不是流。这是更新后的集团代码:
class NearestRestaurant {
final String id;
final Restaurant restaurant;
final double distance;
NearestRestaurant({this.id, this.restaurant, this.distance});
}
class NearRestaurantBloc {
final Stream<List<Restaurant>> source;
final Position userCoordinates;
final _stream = StreamController<List<Restaurant>>();
NearRestaurantBloc({
this.source,
this.userCoordinates,
}) {
List<Restaurant> resList = List<Restaurant>();
source.forEach((rest) {
resList.clear();
rest.forEach((res) async {
await Geolocator().distanceBetween(
userCoordinates.latitude,
userCoordinates.longitude,
res.coordinates.latitude,
res.coordinates.longitude,
).then((distance) {
if (res.active && distance < res.deliveryRadius) {
resList.add(res);
}
});
_stream.add(resList);
});
});
}
Stream<List<Restaurant>> get stream => _stream.stream;
}
我有这个 Flutter bloc,它采用 Firebase 餐厅流,根据相对于用户的位置,将根据餐厅位置仅过滤最近的餐厅。它工作正常,但如果我想查看餐厅文档中的任何更改,我必须使用 RefreshIndicator 进行刷新。我错过了什么?提前致谢。
class NearestRestaurant {
final String id;
final Restaurant restaurant;
final double distance;
NearestRestaurant({this.id, this.restaurant, this.distance});
}
class NearRestaurantBloc {
final Future<List<Restaurant>> source;
final Position userCoordinates;
final _stream = StreamController<List<Restaurant>>();
NearRestaurantBloc({
this.source,
this.userCoordinates,
}) {
List<Restaurant> resList = List<Restaurant>();
source.then((rest) {
rest.forEach((res) async {
await Geolocator().distanceBetween(
userCoordinates.latitude,
userCoordinates.longitude,
res.coordinates.latitude,
res.coordinates.longitude,
).then((distance) {
if (res.active && distance < res.deliveryRadius) {
resList.add(res);
}
});
_stream.add(resList);
});
});
}
Stream<List<Restaurant>> get stream => _stream.stream;
void dispose() {
_stream.close();
}
}
class RestaurantQuery extends StatefulWidget {
@override
_RestaurantQueryState createState() => _RestaurantQueryState();
}
class _RestaurantQueryState extends State<RestaurantQuery> {
NearRestaurantBloc bloc;
@override
Widget build(BuildContext context) {
final database = Provider.of<Database>(context, listen: true);
final session = Provider.of<Session>(context);
final userCoordinates = session.position;
bloc = NearRestaurantBloc(
source: database.patronRestaurants(),
userCoordinates: userCoordinates,
);
return StreamBuilder<List<Restaurant>>(
stream: bloc.stream,
builder: (context, snapshot) {
bool stillLoading = true;
var restaurantList = List<Restaurant>();
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.hasData && snapshot.data.length > 0) {
restaurantList = snapshot.data;
}
stillLoading = false;
}
return Scaffold(
appBar: AppBar(
title: Text(
'Restaurants near you',
style: TextStyle(color: Theme.of(context).appBarTheme.color),
),
elevation: 2.0,
),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: RefreshIndicator(
onRefresh: () async {
setState(() {
});
},
child: RestaurantList(
nearbyRestaurantsList: restaurantList,
stillLoading: stillLoading,
),
),
);
},
);
}
@override
void dispose() {
bloc.dispose();
super.dispose();
}
}
在 _RestaurantQueryState
下的 build
方法中,您将在 builder
方法之外返回 scaffold
。最初,restaurantList
为空。因此,您不生成列表。每当流更新时,您都会获取快照数据以更新 restaurantList
。
问题出在这里。即使 restaurantList
已更新,小部件 RestaurantList
也不会更新,因为它在构建器方法之外。您可以使用以下代码。在这里,我们创建了一个包含 RestaurantList
小部件的小部件。每当流更新时,小部件都会更新。
class _RestaurantQueryState extends State<RestaurantQuery> {
NearRestaurantBloc bloc;
@override
Widget build(BuildContext context) {
final database = Provider.of<Database>(context, listen: true);
final session = Provider.of<Session>(context);
final userCoordinates = session.position;
//////////////////////////////////
//initialize RestaurantList widget
//////////////////////////////////
Widget restaurantWidget = RestaurantList(
nearbyRestaurantsList: [],
stillLoading: false,
);
bloc = NearRestaurantBloc(
source: database.patronRestaurants(),
userCoordinates: userCoordinates,
);
return StreamBuilder<List<Restaurant>>(
stream: bloc.stream,
builder: (context, snapshot) {
bool stillLoading = true;
var restaurantList = List<Restaurant>();
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.hasData && snapshot.data.length > 0) {
restaurantList = snapshot.data;
/////////////////////////////
//update the restaurant widget
//////////////////////////////
restaurantWidget = RestaurantList(
nearbyRestaurantsList: restaurantList,
stillLoading: stillLoading,
);
}
stillLoading = false;
}
return Scaffold(
appBar: AppBar(
title: Text(
'Restaurants near you',
style: TextStyle(color: Theme.of(context).appBarTheme.color),
),
elevation: 2.0,
),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
///////////////////////////
//use the restaurant Widget
///////////////////////////
body: restaurantWidget,
),
);
},
);
}
我的错误。我在听未来而不是流。这是更新后的集团代码:
class NearestRestaurant {
final String id;
final Restaurant restaurant;
final double distance;
NearestRestaurant({this.id, this.restaurant, this.distance});
}
class NearRestaurantBloc {
final Stream<List<Restaurant>> source;
final Position userCoordinates;
final _stream = StreamController<List<Restaurant>>();
NearRestaurantBloc({
this.source,
this.userCoordinates,
}) {
List<Restaurant> resList = List<Restaurant>();
source.forEach((rest) {
resList.clear();
rest.forEach((res) async {
await Geolocator().distanceBetween(
userCoordinates.latitude,
userCoordinates.longitude,
res.coordinates.latitude,
res.coordinates.longitude,
).then((distance) {
if (res.active && distance < res.deliveryRadius) {
resList.add(res);
}
});
_stream.add(resList);
});
});
}
Stream<List<Restaurant>> get stream => _stream.stream;
}