导航到新页面时 BLOC 丢失上下文

BLOC losing context when navigating to a new page

我正在使用 BLOC 模式对我的应用程序中的用户进行身份验证。我有一个包装我的应用程序的主要 BlocProvider。以及根据身份验证状态构建的 BlocBuilder。

如果用户未经身份验证,我有引导/介绍屏幕将导航到登录屏幕。

登录屏幕包裹在另一个 BlocProvider 中,其中包含一个将执行登录的按钮,并在登录成功时添加一个登录事件。

问题是当我从入职屏幕导航时,我失去了主要的 authenticationBloc 上下文。推送新屏幕后,我需要做什么才能访问身份验证集团。

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Bloc.observer = SimpleBlocObserver();

  runApp(
    MyApp(),
  );
}

class AuthenticationWrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider<AuthenticationBloc>(
        create: (context) => AuthenticationBloc()..add(AppStarted()),
        child: MyApp(),
      ),
    );
  }
}
class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthenticationBloc, AuthenticationState>(
      listener: (context, state) {
        if (state is Authenticated) {
          _appUserProfileRepository = AppUserProfileRepository();
        }
      },
      child: BlocBuilder<AuthenticationBloc, AuthenticationState>(
        builder: (context, state) {

          _authCredentialHelper = state.authCredentialHelper;

          if (state is Uninitialized) {
            return SplashScreen();
          }

          if (state is Unauthenticated) {
            return OnboardingScreens(authCredentialHelper: _authCredentialHelper);
          }

          if (state is InvalidRegistration) {
            return RegisterProfileScreen(authCredentialHelper: _authCredentialHelper);
          }

          if (state is Authenticated) {
              xxx
          }

          return Scaffold(body: Center(child: LoadingIndicator()));
        },
      ),
    );
  }
}

这是引导屏幕,我在导航时立即松开 authenticationbloc 上下文

class OnboardingScreens extends StatelessWidget {
  final AuthCredentialHelper authCredentialHelper;

  OnboardingScreens({this.authCredentialHelper});

  _pages(BuildContext context) {
    return [
      xxx
    ];
  }

  _getStartedClicked(BuildContext context) {
    Navigator.push(context, MaterialPageRoute(builder: (context) {
      return LoginScreen(authCredentialHelper: authCredentialHelper);
    }));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: IntroductionScreen(
          pages: _pages(context),
          onDone: () => _getStartedClicked(context),
          showSkipButton: true,
          done: xxx
        ),
      ),
    );
  }
}

在 1 处添加断点时,上下文正常,具有 BlocProvider.of(context)

的有效值

步进到 2. 给我一个错误: BlocProvider.of() 使用不包含 AuthenticationBloc 类型的 Cubit 的上下文调用。

  _getStartedClicked(BuildContext context) {
    1----->Navigator.push(context, MaterialPageRoute(builder: (context) {
    2----->return LoginScreen(authCredentialHelper: authCredentialHelper);
    }));
  }

这是登录屏幕代码

class LoginScreen extends StatelessWidget {
  final AuthCredentialHelper authCredentialHelper;

  LoginScreen({this.authCredentialHelper});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.arrow_back, color: darkBlue),
          onPressed: () => Navigator.of(context).pop(),
        ),
        backgroundColor: Colors.transparent,
        elevation: 0.0,
      ),
      body: SafeArea(
        child: Center(
          child: BlocProvider<LoginBloc>(
            create: (context) => LoginBloc(authCredentialHelper: authCredentialHelper),
            child: LoginForm(authCredentialHelper: authCredentialHelper),
          ),
        ),
      ),
    );
  }
}

出现此错误:

The following assertion was thrown building _InheritedProviderScope<LoginBloc>(value: Instance of 'LoginBloc'):
BlocProvider.of() called with a context that does not contain a Cubit of type AuthenticationBloc.

No ancestor could be found starting from the context that was passed to BlocProvider.of<AuthenticationBloc>().

This can happen if the context you used comes from a widget above the BlocProvider.

改变这个:

   Navigator.push(context, MaterialPageRoute(builder: (context) {
      return LoginScreen(authCredentialHelper: authCredentialHelper);
   }));

   Navigator.push(
     context,
     MaterialPageRoute(builder: (contextLoginScreen) {
        return BlocProvider.value(
            value: context.bloc<AuthenticationBloc>(),
            child: LoginScreen(authCredentialHelper: authCredentialHelper));
     }),
   );