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(