我怎样才能让这个 Flutter Bloc 发送更新?

Posted

技术标签:

【中文标题】我怎样才能让这个 Flutter Bloc 发送更新?【英文标题】:How can I have this Flutter Bloc to send updates? 【发布时间】:2020-09-13 06:22:13 【问题描述】:

我有这个 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();
  


【问题讨论】:

【参考方案1】:

_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,
          ),
        );
      ,
    );
  

【讨论】:

谢谢,Mohammed,但它没有用。餐厅更新仍未发布。【参考方案2】:

我的错。我听的是未来而不是流。这是更新后的区块代码:

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 发送更新?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter BLoC:Cubits 比 BLoC 好吗?

React:我怎样才能让这个 React 组件写得更好更高效?

如何使用 flutter_bloc 添加 CircularProgressIndicator

我怎样才能让RecyclerView变得更流畅?

Flutter Bloc 状态管理

Flutter BLoC:管理主要数据类型的状态