web-dev-qa-db-ja.com

InheritedWidget-navigator.pushの後にnullでゲッターが呼び出されました

新しいウィジェットに移動した後、InheritedWidgetにアクセスしようとすると問題が発生します。

私はこのようなトップレベルのウィジェットを持っています

_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でInheritedWidgetにアクセスしたい

_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;
  }
}
_

しかし、InheritedWidgetの.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ビルダーメソッドのコンテキストに関係しているという印象を持っています。 Navigator.PushなしでLoginScreenウィジェットを使用すると、InheritedWidgetを完全に使用できるため

LoginBlocProvider.of()メソッドに渡されたコンテキストがインスタンスを見つけられないため、エラーが発生しています。

これについて何か考えはありますか?

6
Sebastian

あなたが提供したコードでは、LoginScreenLoginBlocProviderの子孫ではないため、祖先ウィジェットを見つけることができません。コードはWelcomeScreenルートをLoginBlocProviderにラップしますが、ナビゲーター全体をラップしません。解決策は、MaterialAppLoginBlocProviderでラップすることです。これにより、アプリ内のどこからでもアクセスできるようになります。

class App extends StatelessWidget {
  @override
  Widget build(context) {
    return LoginBlocProvider(
      child: MaterialApp(
        title: 'Iniciar Sesion',
        home: WelcomeScreen(),
      ),
    );
  }
}
12
Kirollos Morkos

InheritedWidgetは完全なMatrialAppウィジェット(ルートウィジェット)をラップする必要があります

0
MSaudi