查找提供者上下文的颤振问题

Flutter problem with finding provider context

我对 Flutter Provider 模式有疑问。将用户重定向到新屏幕后,找不到提供程序。

继我之前的问题 () 我写了这段代码:

class NewRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Tap to select';
    return MaterialApp(
        title: title,
        home: Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body: NewRouteBody()
        ));
  }
}

class NewRouteBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var user = Provider.of<UserRepository>(context);
    return ListView(...)

我做了同样的事情,但我再次收到错误消息,提示无法在此小部件 (NewRouteBody) 上方找到正确的提供程序。

试图以某种方式修复它,用谷歌搜索了几个小时的答案但没有成功...

感谢任何帮助。

编辑

这是 UserRepository,其中包含模式:

class UserRepository with ChangeNotifier {
  User user;
  Status _status = Status.Uninitialized;

  Status get status => _status;
  User get getUser => user;
...}

编辑 2:

带有 ChangeNotifier 的代码片段:

void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<UserRepository>(
      builder: (context) => UserRepository.instance(),
      child: Consumer<UserRepository>(
        builder: (context, UserRepository userRepository, _) {
          switch (userRepository.status) {
            case Status.Uninitialized:
              return Login();
            case Status.Unauthenticated:
              return Login();
            case Status.Authenticating:
            case Status.Authenticated:

              if(userRepository.getUser.isPrefSet == 0){
                return Selection();
              }
              return Dashboard();
          }
        },
      ),
    );
  }
}

您首先需要创建 Provider 并将其放置在 usage 上方的树中。 例如,在您的情况下:

  Widget build(BuildContext context) {
final title = 'Tap to select';
return MaterialApp(
    title: title,
    home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Provider<UserRepository> (
          builder: (context) => UserRepository(),
            dispose: (context, val) => val.dispose(),
            child: NewRouteBody())
    ));

}

问题是:

您的 ChangeNotifierProvider 位于 Home 内,但您正试图访问它 outside Home .

提供商是有范围的。这意味着如果它位于小部件树中,则只有它的后代才能访问它。因此,在您的代码中,只有 Home 可以从提供程序读取。

要解决此问题,请将提供程序移到 MaterialApp:

上方
ChangeNotifierProvider<UserRepository> (
  builder: (context) => UserRepository(),
  child: MaterialApp(
    home: Home(),
  ),
)

当应用程序报这样的错误时,可能有多种原因。就我而言,我试图从未被 BlocProvider 从其祖先包装的上下文中读取数据。

// In my Child Widget
Navigator.push(context, MaterialPageRoute(
   builder: (_) => MultiBlocProvider(providers: [
                  BlocProvider.value(
                      value: SaveJobsCubit()),
                  BlocProvider.value(
                      value: context.read<OnlineCompaniesCubit>()),
                  BlocProvider.value(
                      value: context.read<ApplyJobsCubit>()),
                  ], 
               child: AttractiveJobsScreen(),
             )
// But in Parent Widget, I create MultiBlocProvider with case have access_token
AuthRepo.accessToken != null
    ? RepositoryProvider(
        create: (context) => OnlineCompaniesRepo(),
        child: MultiBlocProvider(
          providers: [
            BlocProvider(
              create: (context) => SaveJobsCubit(),
            ),
            BlocProvider(
              create: (context) => OnlineCompaniesCubit(context.read<OnlineCompaniesRepo>()),
            ),
            BlocProvider(
              lazy: false,
              create: (context) => ApplyJobsCubit(),
            ),
          ],
          child: current,
        ),
      )
    : RepositoryProvider(
        create: (context) => OnlineCompaniesRepo(),
        child: BlocProvider(
          create: (context) => OnlineCompaniesCubit(context.read<OnlineCompaniesRepo>()),
          child: current,
        ),
      );

如果没有access_token就会报错,那么子屏就没有SaveJobsCubit,就会出现上面的错误

希望这对某人有所帮助。