InheritedWidget - The getter was called on null after navigator.push

InheritedWidget - The getter was called on null after navigator.push



I'm having trouble trying to access an InheritedWidget after navigating to a new widget.



I have my top level widget like this


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




Then WelcomeScreen has a button to navigate to 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()
));

);




Finally in LoginScreen I want to access the 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(),
],
),
);




Edited: Here it's the 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;




But, when I run the .of method of the InheritedWidget I get this error


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



I have the impression that it all has to do with the context in the Navigator.push builder method.
Because if I use the LoginScreen widget without the Navigator.push, I can use the InheritedWidget perfectly fine



The error is happening because the context passed to the LoginBlocProvider.of() method is not finding the instance.


LoginBlocProvider.of()



Any thoughts on this?






Hi @Sebastian. 1. Your code does not show the LoginBlocProvider (could you please share). 2. I don't understand why you get the bloc in the didChangeDependencies. I would rather a) get it from the build method, before the return Scaffold or, b) Add an void initState(){super.initState();WidgetsBinding.instance.addPostFrameCallback((_)bloc = LoginBlocProvider.of(context);); Could you please try and/or answer? Cheers.

– boeledi
Sep 10 '18 at 21:07






@boeledi I updated the question with the LoginBlocProvider. I try to get the bloc in the didChangeDependencies method because after that I will set up a stream listener. I didn't do it in initState() because I don't have access to the context.

– Sebastian
Sep 10 '18 at 21:14






@boeledi One more thing. This issue goes beyond where I place the call to the inherited widget. For example if I place it in the build function I get the same getter called on null error. That's what's throwing me off. And that's why I thing it had something to do with the navigator.push method

– Sebastian
Sep 10 '18 at 21:23






@Sebastian you have access to context anywhere within a State class, so you can use it in initState. See here: docs.flutter.io/flutter/widgets/State/context.html

– Kirollos Morkos
Sep 10 '18 at 22:30


context


initState






@KirollosMorkos Thanks for your answer, but the problem I'm having is not about accessing the context of the widget (see my last comment)

– Sebastian
Sep 10 '18 at 23:06




1 Answer
1



In the code you've provided, LoginScreen is not a descendant of LoginBlocProvider which is why it can't find the ancestor widget. Your code wraps the WelcomeScreen route in LoginBlocProvider, but not the whole navigator. The solution is to wrap your MaterialApp in LoginBlocProvider and then you will have access to it everywhere in your app.


LoginScreen


LoginBlocProvider


WelcomeScreen


LoginBlocProvider


MaterialApp


LoginBlocProvider


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







That make sense, would you mind giving some more detail about it? If i wanted to place a BlocProvider after some navigation, how can I achieve that?

– Sebastian
Sep 11 '18 at 2:39






Just updated my answer to show that! When you use a MaterialApp, it actually bundles a lot of commonly used widgets together for you, including a Navigator. By putting your LoginBlocProvider outside the MaterialApp, you can guarantee that all routes in your app will have access to it.

– Kirollos Morkos
Sep 11 '18 at 2:43






Thank you so much for your answer. I'll try it

– Sebastian
Sep 11 '18 at 2:50






No problem, glad I could help!

– Kirollos Morkos
Sep 11 '18 at 2:50






If i wanted to place a BlocProvider after some navigation, how can I achieve that? @KirollosMorkos

– Krishnakumar CN
Feb 7 at 9:37



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)