Flutter 使用不包含TrackingBloc类型的Bloc的上下文调用BlocProvider.of()

Flutter 使用不包含TrackingBloc类型的Bloc的上下文调用BlocProvider.of(),flutter,bloc,Flutter,Bloc,我试图提供一个TrackingBloc到MapScreen但是当从onPressed发送事件时,我得到了错误BlocProvider.of(),调用的上下文不包含TrackingBloc类型的Bloc。 MapScreen也使用main()提供的MapBloc,但对于TrackingBloc我想将其设置为本地,而不是使main()中的MultiBlocProvider混乱。 我试过: 要在BlocListener中使用bloc:参数,我被告知它只是将bloc作为BlocProvider提供,但它

我试图提供一个
TrackingBloc
MapScreen
但是当从
onPressed
发送事件时,我得到了错误
BlocProvider.of(),调用的上下文不包含TrackingBloc类型的Bloc。
MapScreen
也使用
main()
提供的
MapBloc
,但对于
TrackingBloc
我想将其设置为本地,而不是使
main()中的
MultiBlocProvider
混乱。 我试过:

  • 要在
    BlocListener
    中使用
    bloc:
    参数,我被告知它只是将bloc作为
    BlocProvider提供,但它不起作用
  • 然后我尝试将
    MultiBlocLister
    作为
    MultiBlocProvider
    的子对象,并在那里设置
    TrackingBloc
    ,但仍然得到了消息
  • 在`main()中的
    MultiBlocProvider
    中设置
    TrackingBloc
    ,并按预期工作
  • 为什么1和2不向树提供
    TrackingBloc
    ? 非常感谢你的帮助

    地图屏幕:

    class MapScreen extends StatefulWidget {
      final String name;
      final MapRepository _mapRepository;
    
      MapScreen(
          {Key key, @required this.name, @required MapRepository mapRepository})
          : assert(mapRepository != null),
            _mapRepository = mapRepository,
            super(key: key);
    
      @override
      _MapScreenState createState() => _MapScreenState();
    }
    
    class _MapScreenState extends State<MapScreen> {
      List<Marker> alerts;
      LatLng userLocation;
    
      MapController _mapController = MapController();
    
      @override
      Widget build(BuildContext context) {
        return MultiBlocProvider(
          providers: [
            BlocProvider<TrackingBloc>(create: (context) {
              return TrackingBloc();
            }),
          ],
          child: MultiBlocListener(
            listeners: [
              BlocListener<MapBloc, MapState>(
                  listener: (BuildContext context, MapState state) {
                if (state is LocationStream) {
                  setState(() {
                    userLocation = (state).location;
    //              print(
    //                  ' @@@@ MapBloc actual user location from stream  is : $userLocation');
                  });
                }
                if (state is MapCenter) {
                  userLocation = (state).location;
    //            print(' @@@@ MapBloc initial center location is : $userLocation');
                  _mapController.move(userLocation, 16);
                }
              }),
              BlocListener<TrackingBloc, TrackingState>(
    //              bloc: TrackingBloc(),
                  listener: (BuildContext context, TrackingState state) {
                if (state is TrackedRoute) {
                  List<Position> route = (state).trackedRoute;
                  print(route);
                }
              }),
            ],
            child: Scaffold(
    
    class MapScreen扩展了StatefulWidget{
    最后的字符串名;
    最终地图存储库\u地图存储库;
    地图屏幕(
    {Key Key、@required this.name、@required MapRepository MapRepository})
    :assert(mapRepository!=null),
    _mapRepository=mapRepository,
    超级(键:键);
    @凌驾
    _MapScreenState createState()=>\u MapScreenState();
    }
    类_MapScreenState扩展状态{
    列出警报;
    LatLng用户位置;
    MapController _MapController=MapController();
    @凌驾
    小部件构建(构建上下文){
    返回多BlocProvider(
    供应商:[
    BlocProvider(创建:(上下文){
    return TrackingBloc();
    }),
    ],
    孩子:多布卢克利斯滕(
    听众:[
    布洛克斯腾纳(
    侦听器:(BuildContext上下文,MapState){
    如果(状态为LocationStream){
    设置状态(){
    userLocation=(state).location;
    //印刷品(
    //“@@@@MapBloc流中的实际用户位置为:$userLocation”);
    });
    }
    如果(状态为地图中心){
    userLocation=(state).location;
    //打印('@@@@MapBloc初始中心位置为:$userLocation');
    _mapController.move(userLocation,16);
    }
    }),
    布洛克斯腾纳(
    //bloc:TrackingBloc(),
    侦听器:(BuildContext上下文,TrackingState状态){
    如果(状态为TrackedRoute){
    列表路由=(状态).trackedRoute;
    印刷(路线);
    }
    }),
    ],
    孩子:脚手架(
    
    main():

    runApp(
    多气泡发生器(
    供应商:[
    BlocProvider(
    创建:(上下文){
    返回AuthenticationBloc(
    userRepository:userRepository(),
    )…添加(AppStarted());
    },
    ),
    BlocProvider(创建:(上下文){
    返回MapBloc(
    mapRepository:mapRepository,
    )
    …添加(GetLocationStream())
    ..添加(GetLocation());
    }),
    BlocProvider(创建:(上下文){
    return TrackingBloc();
    }),
    //BlocProvider(创建:(上下文){
    //返回警报组(
    //alertRepository:alertRepository,
    //)…添加(LoadAlerts());
    //        }),
    ],
    儿童:
    
    在蝙蝠的右边,我可以看到你的代码有两个地方出了问题

    首先:在主屏幕和地图屏幕中提供多个TrackingBloc

    Second:您正在提供跟踪Bloc的同一上下文中通过BlocListener访问跟踪Bloc(第二个
    BlocProvider(创建:(上下文){return TrackingBloc();})
    )。我猜这就是导致错误的原因

    使用不包含TrackingBloc类型的Bloc的上下文调用BlocProvider.of()


    我想只要在MapScreen中删除BlocProvider就可以了。

    我在小部件树的错误位置提供了
    跟踪Bloc
    。 我可以在全局范围内提供我不需要的bloc,因此要在本地提供我想要的bloc,我必须从
    main()
    中的
    Blocbuilder
    提供它,它将返回
    MapScreen

    从以下位置更改
    main()

        return MaterialApp(
          home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
            builder: (context, state) {
              if (state is Unauthenticated) {
                return LoginScreen(userRepository: _userRepository);
              }
              if (state is Authenticated) {
    //            BlocProvider.of<MapBloc>(context).add(GetLocationStream());
    //            BlocProvider.of<AlertBloc>(context).add(LoadAlerts());
                return MapScreen(
                  mapRepository: _mapRepository,
                  name: state.displayName,
    //              alertRepository: FirebaseAlertRepository(),
                );
              }
              if (state is Unauthenticated) {
                return LoginScreen(userRepository: _userRepository);
              }
              return SplashScreen();
            },
          ),
        );
    
    希望这将帮助那些刚开始使用
    flatter\u bloc
    的人,他们可能无法清楚地找到关于其小部件的文档使用说明。 仍然必须完全理解
    BlocProvider
    BlocListener
    bloc:
    属性。。
    干杯。

    Jonathan。我实际上找到了提供
    TrackingBloc
    的正确位置,我会把它放在我的问题的答案中,但让我解释一下困惑是什么。我想提供
    TrackingBloc
    MapScreen
    是因为我希望它只对该屏幕可用。所以首先我尝试在
    bloc中传递它:
    BlocListener
    的参数,从我链接的评论中被误导。这并没有像我期望的那样提供
    跟踪bloc
    ,所以我尝试直接在
    地图屏幕中提供它,但当然(现在我知道了)这也没有提供bloc。仍然在全球范围内提供它显然是有效的。因此解决方案是在我对
    AuthenticationState
    进行的状态检查中提供
    TrackingBloc
    ,并从中返回各种屏幕,包括
    MapScreen
    (参见解决方案)因此,我左思右想的是
    bloc:
    BlocBuilder
    BlocListener
    的参数究竟是什么。它们是否是链接注释中告诉我的新bloc的小部件三的入口点(现在看起来不像…),而我只是没有写正确的代码
        return MaterialApp(
          home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
            builder: (context, state) {
              if (state is Unauthenticated) {
                return LoginScreen(userRepository: _userRepository);
              }
              if (state is Authenticated) {
    //            BlocProvider.of<MapBloc>(context).add(GetLocationStream());
    //            BlocProvider.of<AlertBloc>(context).add(LoadAlerts());
                return MapScreen(
                  mapRepository: _mapRepository,
                  name: state.displayName,
    //              alertRepository: FirebaseAlertRepository(),
                );
              }
              if (state is Unauthenticated) {
                return LoginScreen(userRepository: _userRepository);
              }
              return SplashScreen();
            },
          ),
        );
    
    return MaterialApp(
          home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
            builder: (context, state) {
              if (state is Unauthenticated) {
                return LoginScreen(userRepository: _userRepository);
              }
              if (state is Authenticated) {
    //            BlocProvider.of<MapBloc>(context).add(GetLocationStream());
    //            BlocProvider.of<AlertBloc>(context).add(LoadAlerts());
                return MultiBlocProvider(
                  providers: [
                    BlocProvider<TrackingBloc>(create: (context) {
                      return TrackingBloc();
                    }),
                  ],
                  child: MapScreen(
                    mapRepository: _mapRepository,
                    name: state.displayName,
    //              alertRepository: FirebaseAlertRepository(),
                  ),
                );
                return MapScreen(
                  mapRepository: _mapRepository,
                  name: state.displayName,
    //              alertRepository: FirebaseAlertRepository(),
                );
              }
              if (state is Unauthenticated) {
                return LoginScreen(userRepository: _userRepository);
              }
              return SplashScreen();
            },
          ),
        );
    
    class _MapScreenState extends State<MapScreen> {
      List<Marker> alerts;
      LatLng userLocation;
    
      MapController _mapController = MapController();
    
      @override
      Widget build(BuildContext context) {
        return MultiBlocListener(
          listeners: [
            BlocListener<MapBloc, MapState>(
                listener: (BuildContext context, MapState state) {
              if (state is LocationStream) {
                setState(() {
                  userLocation = (state).location;
    //              print(
    //                  ' @@@@ MapBloc actual user location from stream  is : $userLocation');
                });
              }
              if (state is MapCenter) {
                userLocation = (state).location;
    //            print(' @@@@ MapBloc initial center location is : $userLocation');
                _mapController.move(userLocation, 16);
              }
            }),
            BlocListener<TrackingBloc, TrackingState>(
    //              bloc: TrackingBloc(),
                listener: (BuildContext context, TrackingState state) {
    //      userLocation = (state as LocationStream).location;
              if (state is TrackedRoute) {
                List<Position> route = (state).trackedRoute;
                print(route);
    //            initialLocation = (state).location.then((value) {
    //              print('@@@@@@ value is : $value');
    ////              _mapController.move(value, 16.0);
    //              return value;
    //            }
    //            );
              }
            }),
          ],
          child: Scaffold(