Я собираюсь описать мою проблему и ошибку, с которой я столкнулся. А потом я скопирую свой код, чтобы сделать его более понятным. Проблема как:
- Я использую MultiBlocProvider в root виджет (StartupScreen) с объявленными 2 блоками AuthenticationBlo c, ApplicationBlo c.
- Использование
BlocListener<AuthenticationBloc, AuthenticationState>
at root widget (StartupScreen). - Если состояние AuthenticationBlo c изменяется на AuthAuthenticatedState, то выполняется маршрутизация на MainScreen, в противном случае - на LoginScreen.
- Если пользователь подключился, то выполняется маршрутизация на MainScreen:
- Я собираюсь получить currentUser из хранилища (асинхронно), а затем обернуть BlocListener внутренним FutureBuilder. в итоге он не может отобразить экран и выдает ошибку следующим образом:
BlocProvider.of() called with a context that does not contain a Bloc of type ApplicationBloc.
No ancestor could be found starting from the context that was passed to BlocProvider.of<ApplicationBloc>().
This can happen if the context you used comes from a widget above the BlocProvider.
The context used was: BlocListener<ApplicationBloc, ApplicationState>(dirty, state: _BlocListenerBaseState<ApplicationBloc, ApplicationState>#1abf7(lifecycle state: created))
The relevant error-causing widget was
FutureBuilder<UserCredentials> package:my_app/…/ui/main_screen.dart:43
When the exception was thrown, this was the stack
#0 BlocProvider.of package:flutter_bloc/src/bloc_provider.dart:106
#1 _BlocListenerBaseState.initState package:flutter_bloc/src/bloc_listener.dart:160
#2 StatefulElement._firstBuild package:flutter/…/widgets/framework.dart:4355
#3 ComponentElement.mount package:flutter/…/widgets/framework.dart:4201
#4 SingleChildWidgetElementMixin.mount package:nested/nested.dart:223
...
StartupScreen.dart
class StartupScreen extends StatelessWidget {
final ApplicationBloc appBloc;
final AuthenticationBloc authBloc;
StartupScreen(this.appBloc, this.authBloc) : super();
@override
Widget build(BuildContext context) {
ScreenSizeConfig().init(context);
authBloc.add(AuthStartedEvent());
return MultiBlocProvider(
providers: [
BlocProvider<ApplicationBloc>(
create: (context) => appBloc,
),
BlocProvider<AuthenticationBloc>(
create: (context) => authBloc,
),
],
child: BlocListener<AuthenticationBloc, AuthenticationState>(
listener: (context, state) {
if (state is AuthUnauthenticatedState) {
Navigator.of(context).pushReplacementNamed(RouteConstants.LOGIN_SCREEN);
} else if (state is AuthAuthenticatedState) {
Navigator.of(context).pushReplacementNamed(RouteConstants.MAIN_SCREEN);
}
},
child: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
return Center(
child: Container(
child: Text('Startup Screen'),
),
);
},
),
),
);
}
}
MainScreen.dart
class MainScreen extends StatelessWidget {
final ApplicationBloc appBloc;
final AuthenticationBloc authBloc;
MainScreen(this.appBloc, this.authBloc) : super();
@override
Widget build(BuildContext context) {
return _MainPageWidget(appBloc, authBloc);
}
}
class _MainPageWidget extends StatefulWidget {
final ApplicationBlocappBloc;
final AuthenticationBloc authBloc;
_MainPageWidget(this.appBloc, this.authBloc) : super();
@override
State<StatefulWidget> createState() => _MainPageState();
}
class _MainPageState extends State<_MainPageWidget> {
Future<UserCredentials> getUserCredentials() async {
return await widget.appBloc.authService.getUser();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder<UserCredentials>(
future: getUserCredentials(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return _buildBlocListener(snapshot.data);
}
});
}
Widget _buildBlocListener(UserCredentials userCredentials) {
return BlocListener<ApplicationBloc, ApplicationState>(
listener: (context, state) {
if (userCredentials.isNewUser) {
widget.appBloc.add(AppNewUserEvent());
} else {
widget.appBloc
.add(AppAlreadyCompletedNewUserProcessEvent());
}
},
child: _buildBlocBuilder(context, widget.appBloc),
);
}
Widget _buildBlocBuilder(BuildContext context, ApplicationBloc appBloc) {
return BlocBuilder<ApplicationBloc, ApplicationState>(
builder: (context, state) {
print('main_screen.dart: go to mainscreen BlocBuilder builder: state: $state');
return Container(
child: Text('Main Screen'),
);
},
);
}
}