Как я могу получить Flutter Blo c для отправки обновлений? - PullRequest
0 голосов
/ 26 мая 2020

У меня есть этот Flutter blo c, который принимает поток ресторанов Firebase и в зависимости от положения относительно пользователя будет фильтровать только самые близкие из них в зависимости от местоположения ресторана. Он работает нормально, но мне нужно обновить sh с помощью 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();
  }

}

Ответы [ 2 ]

0 голосов
/ 28 мая 2020

Моя ошибка. Я слушал будущее вместо потока. Вот обновленный код blo c:

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;

}
0 голосов
/ 26 мая 2020

В методе build под _RestaurantQueryState вы возвращаете scaffold вне метода builder. Первоначально restaurantList имеет значение null. Следовательно, вы не составляете список. Каждый раз, когда поток обновляется, вы получаете данные моментального снимка для обновления 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,
          ),
        );
      },
    );
  }
...