dart Flutter误差:生成KeyedSubtree时引发以下ProviderNotFoundException,错误:找不到正确的提供程序< AuthCubit>

wfsdck30  于 2023-07-31  发布在  Flutter
关注(0)|答案(1)|浏览(116)

我正在使用Flutter BloC编写我的登录&注册&确认页面。
当我进入“注册页面”时(当我点击该按钮时),我得到了错误。

错误:

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════
The following ProviderNotFoundException was thrown building
KeyedSubtree-[GlobalKey#76df5]:
Error: Could not find the correct Provider<AuthCubit> above this
_InheritedProviderScope<SignUpBloc?> Widget

This happens because you used a `BuildContext` that does not include the
provider
of your choice. There are a few common scenarios:

- You added a new provider in your `main.dart` and performed a hot-reload.
  To fix, perform a hot-restart.

- The provider you are trying to read is in a different route.

  Providers are "scoped". So if you insert of provider inside a route, then
  other routes will not be able to access that provider.

- You used a `BuildContext` that is an ancestor of the provider you are trying
to read.

  Make sure that _InheritedProviderScope<SignUpBloc?> is under your
MultiProvider/Provider<AuthCubit>.
  This usually happens when you are creating a provider and trying to read it
  immediately.

  For example, instead of:

  
  Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // Will throw a ProviderNotFoundError, because `context` is associated
      // to the widget that is the parent of `Provider<Example>`
      child: Text(context.watch<Example>().toString()),
    );
  }
  

  consider using `builder` like so:

  
  Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // we use `builder` to obtain a new `BuildContext` that has access to the
      provider
      builder: (context, child) {
        // No longer throws
        return Text(context.watch<Example>().toString());
      }
    );
  }
  

If none of these solutions work, consider asking for help on StackOverflow:
https://stackoverflow.com/questions/tagged/flutter

The relevant error-causing widget was:
  Scaffold
  Scaffold:file:///Users/kelly_hung/study_savvy_app/lib/screens/sign_up.dart:15:
  12

When the exception was thrown, this was the stack:
#0      Provider._inheritedElementOf (package:provider/src/provider.dart:343:7)
#1      Provider.of (package:provider/src/provider.dart:293:30)
#2      ReadContext.read (package:provider/src/provider.dart:649:21)
#3      main.<anonymous closure>.<anonymous closure>
(package:study_savvy_app/main.dart:81:112)
#4      _CreateInheritedProviderState.value
(package:provider/src/inherited_provider.dart:736:36)
#5      _InheritedProviderScopeElement.value
(package:provider/src/inherited_provider.dart:590:33)
#6      Provider.of (package:provider/src/provider.dart:303:37)
#7      ReadContext.read (package:provider/src/provider.dart:649:21)
#8      _BlocListenerBaseState.initState
(package:flutter_bloc/src/bloc_listener.dart:143:36)
#9      StatefulElement._firstBuild
(package:flutter/src/widgets/framework.dart:5219:55)
#10     ComponentElement.mount
(package:flutter/src/widgets/framework.dart:5062:5)
#11     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
#12     Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3971:16)
#13     MultiChildRenderObjectElement.inflateWidget
(package:flutter/src/widgets/framework.dart:6570:36)
#14     MultiChildRenderObjectElement.mount
(package:flutter/src/widgets/framework.dart:6582:32)
...     Normal element mounting (25 frames)
#39     Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3971:16)
#40     MultiChildRenderObjectElement.inflateWidget
(package:flutter/src/widgets/framework.dart:6570:36)
#41     MultiChildRenderObjectElement.mount
(package:flutter/src/widgets/framework.dart:6582:32)
...     Normal element mounting (134 frames)
#175    Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3971:16)
#176    MultiChildRenderObjectElement.inflateWidget
(package:flutter/src/widgets/framework.dart:6570:36)
#177    MultiChildRenderObjectElement.mount
(package:flutter/src/widgets/framework.dart:6582:32)
...     Normal element mounting (178 frames)
#355    Element.inflateWidget
(package:flutter/src/widgets/framework.dart:3971:16)
#356    MultiChildRenderObjectElement.inflateWidget
(package:flutter/src/widgets/framework.dart:6570:36)
#357    Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#358    RenderObjectElement.updateChildren
(package:flutter/src/widgets/framework.dart:6153:32)
#359    MultiChildRenderObjectElement.update
(package:flutter/src/widgets/framework.dart:6595:17)
#360    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#361    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#362    StatefulElement.performRebuild
(package:flutter/src/widgets/framework.dart:5251:11)
#363    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#364    StatefulElement.update
(package:flutter/src/widgets/framework.dart:5274:5)
#365    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#366    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#367    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#368    ProxyElement.update (package:flutter/src/widgets/framework.dart:5417:5)
#369    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#370    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#371    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#372    ProxyElement.update (package:flutter/src/widgets/framework.dart:5417:5)
#373    _InheritedNotifierElement.update
(package:flutter/src/widgets/inherited_notifier.dart:107:11)
#374    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#375    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#376    StatefulElement.performRebuild
(package:flutter/src/widgets/framework.dart:5251:11)
#377    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#378    StatefulElement.update
(package:flutter/src/widgets/framework.dart:5274:5)
#379    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#380    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#381    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#382    ProxyElement.update (package:flutter/src/widgets/framework.dart:5417:5)
#383    _InheritedNotifierElement.update
(package:flutter/src/widgets/inherited_notifier.dart:107:11)
#384    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#385    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#386    StatefulElement.performRebuild
(package:flutter/src/widgets/framework.dart:5251:11)
#387    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#388    StatefulElement.update
(package:flutter/src/widgets/framework.dart:5274:5)
#389    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#390    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#391    StatefulElement.performRebuild
(package:flutter/src/widgets/framework.dart:5251:11)
#392    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#393    StatefulElement.update
(package:flutter/src/widgets/framework.dart:5274:5)
#394    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#395    SingleChildRenderObjectElement.update
(package:flutter/src/widgets/framework.dart:6442:14)
#396    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#397    SingleChildRenderObjectElement.update
(package:flutter/src/widgets/framework.dart:6442:14)
#398    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#399    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#400    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#401    ProxyElement.update (package:flutter/src/widgets/framework.dart:5417:5)
#402    Element.updateChild (package:flutter/src/widgets/framework.dart:3686:15)
#403    ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:5111:16)
#404    StatefulElement.performRebuild
(package:flutter/src/widgets/framework.dart:5251:11)
#405    Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#406    BuildOwner.buildScope
(package:flutter/src/widgets/framework.dart:2780:19)
#407    WidgetsBinding.drawFrame
(package:flutter/src/widgets/binding.dart:903:21)
#408    RendererBinding._handlePersistentFrameCallback
(package:flutter/src/rendering/binding.dart:358:5)
#409    SchedulerBinding._invokeFrameCallback
(package:flutter/src/scheduler/binding.dart:1284:15)
#410    SchedulerBinding.handleDrawFrame
(package:flutter/src/scheduler/binding.dart:1214:9)
#411    SchedulerBinding._handleDrawFrame
(package:flutter/src/scheduler/binding.dart:1072:5)
#412    _invoke (dart:ui/hooks.dart:142:13)
#413    PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:359:5)
#414    _drawFrame (dart:ui/hooks.dart:112:31)

════════════════════════════════════════════════════════════════════════════════
════════════════════

Another exception was thrown: Each child must be laid out exactly once.
Another exception was thrown: Updated layout information required for
RenderErrorBox#5cb32 NEEDS-LAYOUT NEEDS-PAINT to calculate semantics.

字符串

我的编码:

main.dart:

void main() {
  runApp(DevicePreview(
      enabled: !kReleaseMode,
      builder: (context) => MultiProvider(
            providers: [
              RepositoryProvider(
                create: (context) => AuthRepository(),
              ),
              ChangeNotifierProvider(
                create: (_) => ThemeProvider(),
              ),
              ChangeNotifierProvider(
                create: (_) => OCRImageProvider(),
              ),
              BlocProvider(
                create: (context) => PageBloc(),
              ),
              BlocProvider(
                create: (context) => JWTBloc(),
              ),
              BlocProvider(
                create: (context) => FileBloc(),
              ),
              BlocProvider(
                create: (context) => FilesBloc(),
              ),
              BlocProvider(
                create: (context) => ProfileBloc(),
              ),
              BlocProvider(
                create: (context) => AccessMethodBloc(),
              ),
              BlocProvider(
                create: (context) => ArticleBloc(),
              ),
              BlocProvider(
                create: (context) => PasswordBloc(),
              ),
                BlocProvider(
                  create: (context) => LoginBloc(authRepo: context.read<AuthRepository>(), authCubit: AuthCubit(sessionCubit: SessionCubit(authRepo: AuthRepository())))
                ),
                BlocProvider(
                  create: (context) => SignUpBloc(authRepo: context.read<AuthRepository>(), authCubit: context.read<AuthCubit>())
                ),
              BlocProvider(
                create:  (context) => PasswordBloc(),
              ),
              BlocProvider(
                create:  (context) => OnlineBloc(),
              ),
              BlocProvider(
                create:  (context) 
                            => SessionCubit(authRepo: context.read<AuthRepository>(),),
                child: AppNavigator(), //responsible for showing the view
              ),
            ],
            child: const MyApp(),
          )));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    final themeProvider = Provider.of<ThemeProvider>(context);
    return 
    // RepositoryProvider(
    //   create: (context) => AuthRepository(),
    //   child: 
      MaterialApp(
        locale: DevicePreview.locale(context),
        builder: DevicePreview.appBuilder,
        title: 'Study-Savvy',
        theme: LightStyle.theme,
        darkTheme: DarkStyle.theme,
        themeMode: themeProvider.themeMode,
         //initialRoute: Routes.home,
        onGenerateRoute: RouteGenerator.generateRoute,
        debugShowCheckedModeBanner: false,
        home: Container(
          alignment: Alignment.center,
          decoration: const BoxDecoration(
              image: DecorationImage(
            image: AssetImage('assets/images/initial.jpg'),
            fit: BoxFit.cover,
          )),
          child: const HomePage(),

        )
      //)
      );
  }
}


sign_up.dart:

class SignUpView extends StatelessWidget {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // body: BlocProvider(
      //   create: (context) => SignUpBloc(
      //     authRepo: context.read<AuthRepository>(),
      //     authCubit: context.read<AuthCubit>(),
      //   ),
        //child: 
        body:
        Stack(
          alignment: Alignment.bottomCenter,
          children: [
            _signUpForm(),
            _showLoginButton(context),
          ],
        ),
      //),
    );
  }

  Widget _signUpForm() {
    return BlocListener<SignUpBloc, SignUpState>(
        listener: (context, state) {
          final formStatus = state.formStatus;
          if (formStatus is SubmissionFailed) {
            _showSnackBar(context, formStatus.exception.toString());
          }
        },
        child: Form(
          key: _formKey,
          child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 40),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                _usernameField(),
                _emailField(),
                _passwordField(),
                _signUpButton(),
              ],
            ),
          ),
        ));
  }

  Widget _usernameField() {
    return BlocBuilder<SignUpBloc, SignUpState>(builder: (context, state) {
      return TextFormField(
        decoration: InputDecoration(
          icon: Icon(Icons.person),
          hintText: 'Username',
        ),
        validator: (value) =>
            state.isValidUsername ? null : 'Username is too short',
        onChanged: (value) => context.read<SignUpBloc>().add(
              SignUpUsernameChanged(username: value),
            ),
      );
    });
  }

  Widget _emailField() {
    return BlocBuilder<SignUpBloc, SignUpState>(builder: (context, state) {
      return TextFormField(
        decoration: InputDecoration(
          icon: Icon(Icons.person),
          hintText: 'Email',
        ),
        validator: (value) => state.isValidUsername ? null : 'Invalid email',
        onChanged: (value) => context.read<SignUpBloc>().add(
              SignUpEmailChanged(email: value),
            ),
      );
    });
  }

  Widget _passwordField() {
    return BlocBuilder<SignUpBloc, SignUpState>(builder: (context, state) {
      return TextFormField(
        obscureText: true,
        decoration: InputDecoration(
          icon: Icon(Icons.security),
          hintText: 'Password',
        ),
        validator: (value) =>
            state.isValidPassword ? null : 'Password is too short',
        onChanged: (value) => context.read<SignUpBloc>().add(
              SignUpPasswordChanged(password: value),
            ),
      );
    });
  }

  Widget _signUpButton() {
    return BlocBuilder<SignUpBloc, SignUpState>(builder: (context, state) {
      return state.formStatus is FormSubmitting
          ? CircularProgressIndicator()
          : ElevatedButton(
              onPressed: () {
                if (_formKey.currentState!.validate()) {
                  context.read<SignUpBloc>().add(SignUpSubmitted());
                }
              },
              child: Text('Sign Up'),
            );
    });
  }

  Widget _showLoginButton(BuildContext context) {
    return SafeArea(
      child: TextButton(
        child: Text('Already have an account? Sign in.'),
        onPressed: () => context.read<AuthCubit>().showLogin(),
      ),
    );
  }

  void _showSnackBar(BuildContext context, String message) {
    final snackBar = SnackBar(content: Text(message));
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
  }
}


注册_bloc.dart:

class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
  final AuthRepository authRepo;
  final AuthCubit authCubit;

  SignUpBloc({required this.authRepo, required this.authCubit})
     : super(SignUpState()){
      on<SignUpEvent>(_onEvent);
     }

  Future<void> _onEvent(SignUpEvent event, Emitter<SignUpState> emit) async {
    // Username updated
    if (event is SignUpUsernameChanged) {
      emit(state.copyWith(username: event.username));

      // Email updated
    } else if (event is SignUpEmailChanged) {
      emit(state.copyWith(email: event.email));

      // Password updated
    } else if (event is SignUpPasswordChanged) {
      emit(state.copyWith(password: event.password));

      // Form submitted
    } else if (event is SignUpSubmitted) {
      emit(state.copyWith(formStatus: FormSubmitting()));

      try {
        await authRepo.signUp(
          username: state.username,
          email: state.email,
          password: state.password,
        );
        emit(state.copyWith(formStatus: SubmissionSuccess()));

        authCubit.showConfirmSignUp( 
          username: state.username,
          email: state.email,
          password: state.password,
        );
      } catch (e) {
        emit(state.copyWith(formStatus: SubmissionFailed(e.toString() as Exception)));
      }
    }
  }
}


auth_cubit:

enum AuthState { login, signUp, confirmSignUp }

class AuthCubit extends Cubit<AuthState> {
  final SessionCubit sessionCubit;

  AuthCubit({required this.sessionCubit}) : super(AuthState.login);

  late AuthCredentials credentials;

  void showLogin() => emit(AuthState.login);
  void showSignUp() => emit(AuthState.signUp);
  void showConfirmSignUp({
    required String username,
    required String email,
    required String password,
  }) {
    credentials = AuthCredentials(  //crate right here, to hand on argument
      username: username,
      email: email,
      password: password,
    );
    emit(AuthState.confirmSignUp); //show confirm view
  }

  void launchSession(AuthCredentials credentials) =>
      sessionCubit.showSession(credentials);
}


auth_navigator.dart:

class AuthNavigator extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<AuthCubit, AuthState>(builder: (context, state) {
      return Navigator(
        pages: [
          // Show login
          if (state == AuthState.login) MaterialPage(child: SignInPage()),

          // Allow push animation
          if (state == AuthState.signUp ||
              state == AuthState.confirmSignUp) ...[
            // Show Sign up
            MaterialPage(child: SignUpView()),

            // Show confirm sign up
            if (state == AuthState.confirmSignUp)
              MaterialPage(child: ConfirmationView())
          ]
        ],
        onPopPage: (route, result) => route.didPop(result),
      );
    });
  }
}


session_cubit.dart:

class SessionCubit extends Cubit<SessionState> {
  final AuthRepository authRepo;

  SessionCubit({required this.authRepo}) : super(UnknownSessionState()) {
    attemptAutoLogin();
  }

  void attemptAutoLogin() async {
    try {
      final userId = await authRepo.attemptAutoLogin();
      // final user = dataRepo.getUser(userId);
      final user = userId;
      emit(Authenticated(user: user));
    } on Exception {
      emit(Unauthenticated());
    }
  }

  void showAuth() => emit(Unauthenticated());
  void showSession(AuthCredentials credentials) {
    // final user = dataRepo.getUser(credentials.userId);
    final user = credentials.username;
    emit(Authenticated(user: user));
  }

  void signOut() {
    authRepo.signOut();
    emit(Unauthenticated());
  }
}


app_navigator.dart:

class AppNavigator extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<SessionCubit, SessionState>(builder: (context, state) {
      return Navigator(
        pages: [
          // Show loading screen
          if (state is UnknownSessionState) MaterialPage(child: LoadingView()),

          // Show auth flow
          if (state is Unauthenticated)
            MaterialPage(
              child: BlocProvider(
                create: (context) =>
                    AuthCubit(sessionCubit: context.read<SessionCubit>()),
                child: AuthNavigator(),  
              ),
            ),

          // Show session flow
          if (state is Authenticated) MaterialPage(child: HomePage())
        ],
        onPopPage: (route, result) => route.didPop(result),
      );
    });
  }
}


我按照YouTube上的教程一步一步地(video),并改变了一些细节。例如,我有Initial.dart来导航到一开始的登录/注册页面。
当我选择登录按钮时,应用程序可以正常运行,并进入我的以下页面。
但是,当我点击“注册”按钮时,无论在哪个页面,屏幕都是空的,并发生错误。
谢谢你!!!:))

svgewumm

svgewumm1#

auth Navigator页面移动到sign up页面
你必须提供auth cubitsign up页.
在这里

MaterialPage(child: SignUpView()),

字符串
使用BlocProvider.value并将auth cubit的值提供给signup页面
用这个代替,

MaterialPage(child: BlocProvider.value(
                    value:context.read<AuthCubit>(), child: SignUpView()),


然后它会工作。

相关问题