簡體   English   中英

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

[英]BlocProvider.of() called with a context that does not contain a Bloc of type TrackingBloc

我正在嘗試向MapScreen提供TrackingBloc ,但是當從onPressed發送事件時,我收到錯誤BlocProvider.of() called with a context that does not contain a Bloc of type TrackingBloc. MapScreen還使用從main()提供的MapBloc ,但對於TrackingBloc我想讓它本地化,而不是在main() MultiBlocProvider 我試過:

  1. 要在BlocListener<TrackingBloc, TrackingState>使用bloc:參數,因為我被告知它只是像BlocProvider那樣提供 bloc( https://github.com/felangel/bloc/issues/930#issuecomment- 593790702 )但它沒有用。
  2. 然后我嘗試使MultiBlocLister成為MultiBlocLister的子MultiBlocProvider並在那里設置TrackingBloc ,但仍然收到消息。
  3. 在 `main() 的MultiBlocProvider中設置TrackingBloc MultiBlocProvider預期工作。

為什么 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(

主要的():

  runApp(
    MultiBlocProvider(
      providers: [
        BlocProvider<AuthenticationBloc>(
          create: (context) {
            return AuthenticationBloc(
              userRepository: UserRepository(),
            )..add(AppStarted());
          },
        ),
        BlocProvider<MapBloc>(create: (context) {
          return MapBloc(
            mapRepository: mapRepository,
          )
            ..add(GetLocationStream())
            ..add(GetLocation());
        }),
        BlocProvider<TrackingBloc>(create: (context) {
          return TrackingBloc();
        }),
//        BlocProvider<AlertBloc>(create: (context) {
//          return AlertBloc(
//            alertRepository: alertRepository,
//          )..add(LoadAlerts());
//        }),
      ],
      child:

蝙蝠的右邊,我可以看到您的代碼有兩處錯誤。

第一:您在 main 和 MapScreen 中提供多個 TrackingBloc。

第二:您在提供它的同一上下文中通過 BlocListener 訪問 TrackingBloc(第二個BlocProvider(create: (context) {return TrackingBloc();}) )。 我的猜測是這就是導致錯誤的原因。

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

我認為只需在 MapScreen 中刪除 BlocProvider 就可以完成這項工作。

我從小部件樹中錯誤的位置提供了TrackingBloc 我可以在全局范圍內提供我不需要的 bloc,因此要根據需要在本地提供它,我必須從返回MapScreen main() Blocbuilder提供它。

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();
        },
      ),
    );

到:

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();
        },
      ),
    );

使它按我的意圖工作。 然后在MapScreen我只使用不同的BlocListener來收聽全局作為MapBloc或本地作為TrackingBloc

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(

希望這會幫助其他剛開始使用flutter_bloc ,他們可能無法清楚地找到其小部件的文檔使用說明。 仍然需要完全理解BlocProviderBlocListenerbloc: property 面團..干杯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM