如何从另一个块访问块状态中的数据

IMS*_*Dev 7 flutter flutter-bloc

我正在使用 Bloc 模式开发 Flutter 应用程序。认证成功后,UserSate就有了User对象。在所有其他 Bloc 中,我需要访问 UserState 中的 User 对象。我尝试在其他 Bloc 的构造函数参数上获取 UserBloc 并访问 User 对象。但它显示 User 对象为 null。有人有更好的解决方案吗?

class SectorHomeBloc extends Bloc<SectorHomeEvent, SectorHomeState> {
  final OutletRepository outletRepository;
  UserBloc userBloc;
  final ProductRepository productRepository;
  final ProductSubCategoryRepository productSubCategoryRepository;
  final PromotionRepository promotionRepository;
  final ProductMainCategoryRepository mainCategoryRepository;

  SectorHomeBloc({
    @required this.outletRepository,
    @required this.userBloc,
    @required this.productSubCategoryRepository,
    @required this.productRepository,
    @required this.promotionRepository,
    @required this.mainCategoryRepository,
  });
  @override
  SectorHomeState get initialState => SectorHomeLoadingState();

  @override
  Stream<SectorHomeState> mapEventToState(SectorHomeEvent event) async* {
    try {
      print(userBloc.state.toString());
      LatLng _location = LatLng(
          userBloc.state.user.defaultLocation.coordinate.latitude,
          userBloc.state.user.defaultLocation.coordinate.longitude);
      String _token = userBloc.state.user.token;

      if (event is GetAllDataEvent) {
        yield SectorHomeLoadingState();
        List<Outlet> _previousOrderedOutlets =
            await outletRepository.getPreviousOrderedOutlets(
                _token, _location, event.orderType, event.sectorId);

        List<Outlet> _featuredOutlets =
            await outletRepository.getFeaturedOutlets(
                _token, _location, event.orderType, event.sectorId);
        List<Outlet> _nearestOutlets = await outletRepository.getOutletsNearYou(
            _token, _location, event.orderType, event.sectorId);

        List<Product> _newProducts = await productRepository.getNewItems(
            _token, _location, event.orderType, event.sectorId);

        List<Product> _trendingProducts =
            await productRepository.getTrendingItems(
                _token, _location, event.orderType, event.sectorId);

        List<Promotion> _promotions = await promotionRepository
            .getVendorPromotions(_token, event.sectorId);
        yield SectorHomeState(
          previousOrderedOutlets: _previousOrderedOutlets,
          featuredOutlets: _featuredOutlets,
          nearByOutlets: _nearestOutlets,
          newItems: _newProducts,
          trendingItems: _trendingProducts,
          promotions: _promotions,
        );
      }
    } on SocketException {
      yield SectorHomeLoadingErrorState('could not connect to server');
    } catch (e) {
      print(e);
      yield SectorHomeLoadingErrorState('Error');
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

mapEventToState方法中的打印语句[print(userBloc.state.toString());]显示了UserSate的初始状态。但是,在执行此代码时,UserState 处于 UserLoggedInState 状态。

Bar*_*ban 15

更新(最佳实践):请参阅此处的答案 ,因此最好的方法是听取您所在小部件内另一个块的更改,并据此触发事件。所以你要做的就是将你的小部件包装在一个块监听器中并监听你想要的块。

    class SecondPage extends StatelessWidget {
      const SecondPage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return BlocListener<FirstBloc, FirstBlocState>(
          listener: (context, state) {
             if(state is StateFromFirstBloc){
             BlocProvider.of<SecondBloc>(context).add(SecondBlocEvent());}//or whatever you want
          },
          child: ElevatedButton(
            child:   Text('THIS IS NEW SCREEN'),
            onPressed: () {
              BlocProvider.of<SecondBloC>(context).add(SecondBloCEvent());
            },
          ),
        );
      }
    }
Run Code Online (Sandbox Code Playgroud)

Listener 的可爱之处在于,您可以在任何地方收听任何集团并做任何您想做的事情这里是它的官方文档

老方法(不推荐)

有一种官方方法可以做到这一点,如文档中所示,称为Bloc-to-Bloc Communication ,这里是文档中的示例

class MyBloc extends Bloc {
  final OtherBloc otherBloc;
  StreamSubscription otherBlocSubscription;

  MyBloc(this.otherBloc) {
    otherBlocSubscription = otherBloc.listen((state) {
        // React to state changes here.
        // Add events here to trigger changes in MyBloc.
    });
  }

  @override
  Future<void> close() {
    otherBlocSubscription.cancel();
    return super.close();
  }
}
Run Code Online (Sandbox Code Playgroud)

抱歉这个答案更新较晚,感谢@MJ studio


小智 6

接受的答案实际上在官方文档中的上述示例中有一条评论说“无论您多么想这样做,您都不应该这样做!继续阅读以获得更好的替代方案!”!!!

这是官方文档链接,最终一个集团不应该知道任何其他集团,添加方法来更新您的集团,这些可以从侦听其他集团中的更改的 blocListeners 触发:https ://bloclibrary.dev/#/architecture ?id=通过域连接块

class MyWidget extends StatelessWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<WeatherCubit, WeatherState>(
      listener: (context, state) {
        // When the first bloc's state changes, this will be called.
        //
        // Now we can add an event to the second bloc without it having
        // to know about the first bloc.
        BlocProvider.of<SecondBloc>(context).add(SecondBlocEvent());
      },
      child: TextButton(
        child: const Text('Hello'),
        onPressed: () {
          BlocProvider.of<FirstBloc>(context).add(FirstBlocEvent());
        },
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)