[英]Flutter BLoC BlocProvider.of() called with a context that does not contain a Bloc of type
[英]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
。 我試過:
BlocListener<TrackingBloc, TrackingState>
使用bloc:
參數,因為我被告知它只是像BlocProvider
那樣提供 bloc( https://github.com/felangel/bloc/issues/930#issuecomment- 593790702 )但它沒有用。MultiBlocLister
成為MultiBlocLister
的子MultiBlocProvider
並在那里設置TrackingBloc
,但仍然收到消息。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
,他們可能無法清楚地找到其小部件的文檔使用說明。 仍然需要完全理解BlocProvider
和BlocListener
的bloc:
property 面團..干杯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.