首页 > 解决方案 > 我怎样才能让这个 Flutter Bloc 发送更新?

问题描述

我有这个 Flutter 集团,它采用 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();
  }

}

标签: firebaseflutterbloc

解决方案


build下的方法中_RestaurantQueryState,您将返回该方法的scaffold外部builder。最初,restaurantList为空。因此,您不会生成列表。每当流更新时,您都会获取快照数据以更新restaurantList.

问题出现在这里。即使restaurantList已更新,小部件RestaurantList也不会更新,因为它在 builder 方法之外。您可以使用以下代码。在这里,我们创建一个包含小部件的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,
          ),
        );
      },
    );
  }

推荐阅读