代码之家  ›  专栏  ›  技术社区  ›  Sebastian

InheritedWidget-在navigator.push之后,getter被调用为空。

  •  4
  • Sebastian  · 技术社区  · 8 年前

    导航到新的小部件后,我在尝试访问继承的小部件时遇到问题。

    我有这样的顶级小工具

    class App extends StatelessWidget{
      build(context){
        return MaterialApp(
            title: 'Iniciar Sesion',
            home: LoginBlocProvider(child: WelcomeScreen()),
        );
      }  
    }
    

    然后welcomescreen有一个按钮导航到loginscreen

    class WelcomeScreen extends StatelessWidget {
    
      @override Widget build(BuildContext context){
        return Scaffold(
          body: Center(child: MyButton)
        );
      }
    }
    
    class MyButton extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return RaisedButton(
          shape: StadiumBorder(),
          child: Text('Ingresar', style: TextStyle(color: Colors.black)),
          elevation: 5.0,
          onPressed: () { 
            Navigator.of(context).push(MaterialPageRoute(
               builder: (BuildContext context) =>LoginScreen()
            ));
          }
        );
      }
    }
    

    最后在Loginscreen中,我想访问继承的小部件

    class LoginScreen extends StatefulWidget {
      @override
      _LoginScreenState createState() => _LoginScreenState();
    }
    
    class _LoginScreenState extends State<LoginScreen> {
      LoginBloc bloc;  
    
      @override void didChangeDependencies() {
        bloc = LoginBlocProvider.of(context);
        super.didChangeDependencies();
      }
    
      @override Widget build(BuildContext context){
        return Scaffold(
          body:
          Stack(
            fit: StackFit.expand,
            children: <Widget>[
              Positioned(
                top: 0.0,
                child: Image.asset('assets/images/img.jpg',
                  fit: BoxFit.none,
                ),
              ),
              _buildLogin(),
            ],
          ),
        );
      }
    }
    

    编辑: 这里是LoginBlocProvider

    class LoginBlocProvider extends InheritedWidget {
      final bloc;
    
      LoginBlocProvider({Key key, Widget child}) 
      : bloc = LoginBloc(), 
      super(key:key, child:child);
    
      @override
      bool updateShouldNotify(InheritedWidget oldWidget) => true;
    
      static LoginBloc of(BuildContext context) {
        return (context.inheritFromWidgetOfExactType(LoginBlocProvider) as LoginBlocProvider).bloc;
      }
    }
    

    但是,当我运行继承的小部件的.of方法时,我会得到这个错误

    I/flutter (27725): The following NoSuchMethodError was thrown building Builder:
    I/flutter (27725): The getter 'bloc' was called on null.
    I/flutter (27725): Receiver: null
    I/flutter (27725): Tried calling: bloc
    

    我觉得这一切都与navigator.push builder方法中的上下文有关。 因为如果我在没有navigator.push的情况下使用loginscreen小部件,我可以完美地使用继承的小部件。

    发生错误的原因是上下文传递到 LoginBlocProvider.of() 方法找不到实例。

    有什么想法吗?

    1 回复  |  直到 7 年前
        1
  •  8
  •   Kirollos Morkos    7 年前

    在你提供的代码中, LoginScreen 不是的后代 LoginBlocProvider 这就是为什么它找不到祖先小部件的原因。您的代码将 WelcomeScreen 进路 登录锁定提供程序 但不是整个领航员。解决办法是把你的 MaterialApp 在里面 登录锁定提供程序 然后你可以在应用程序的任何地方访问它。

    class App extends StatelessWidget {
      @override
      Widget build(context) {
        return LoginBlocProvider(
          child: MaterialApp(
            title: 'Iniciar Sesion',
            home: WelcomeScreen(),
          ),
        );
      }
    }
    
    推荐文章