I have a StatefulWidget
which I want to use in named route. I have to pass some arguments which I am doing as suggested in https://flutter.dev/docs/cookbook/navigation/navigate-with-arguments i.e.
Navigator.pushNamed( context, routeName, arguments: <args>, );
Now, I need to access these argument's in the state's initState
method as the arguments are needed to subscribe to some external events. If I put the args = ModalRoute.of(context).settings.arguments;
call in initState
, I get a runtime exception.
20:49:44.129 4 info flutter.tools I/flutter ( 2680): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ 20:49:44.129 5 info flutter.tools I/flutter ( 2680): The following assertion was thrown building Builder: 20:49:44.129 6 info flutter.tools I/flutter ( 2680): inheritFromWidgetOfExactType(_ModalScopeStatus) or inheritFromElement() was called before 20:49:44.130 7 info flutter.tools I/flutter ( 2680): _CourseCohortScreenState.initState() completed. 20:49:44.130 8 info flutter.tools I/flutter ( 2680): When an inherited widget changes, for example if the value of Theme.of() changes, its dependent 20:49:44.131 9 info flutter.tools I/flutter ( 2680): widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor 20:49:44.131 10 info flutter.tools I/flutter ( 2680): or an initState() method, then the rebuilt dependent widget will not reflect the changes in the 20:49:44.131 11 info flutter.tools I/flutter ( 2680): inherited widget. 20:49:44.138 12 info flutter.tools I/flutter ( 2680): Typically references to inherited widgets should occur in widget build() methods. Alternatively, 20:49:44.138 13 info flutter.tools I/flutter ( 2680): initialization based on inherited widgets can be placed in the didChangeDependencies method, which 20:49:44.138 14 info flutter.tools I/flutter ( 2680): is called after initState and whenever the dependencies change thereafter. 20:49:44.138 15 info flutter.tools I/flutter ( 2680): 20:49:44.138 16 info flutter.tools I/flutter ( 2680): When the exception was thrown, this was the stack: 20:49:44.147 17 info flutter.tools I/flutter ( 2680): #0 StatefulElement.inheritFromElement.<anonymous closure> (package:flutter/src/widgets/framework.dart:3936:9) 20:49:44.147 18 info flutter.tools I/flutter ( 2680): #1 StatefulElement.inheritFromElement (package:flutter/src/widgets/framework.dart:3969:6) 20:49:44.147 19 info flutter.tools I/flutter ( 2680): #2 Element.inheritFromWidgetOfExactType (package:flutter/src/widgets/framework.dart:3285:14) 20:49:44.147 20 info flutter.tools I/flutter ( 2680): #3 ModalRoute.of (package:flutter/src/widgets/routes.dart:698:46) 20:49:44.147 21 info flutter.tools I/flutter ( 2680): #4 _CourseCohortScreenState.initState.<anonymous closure> (package:esk2/cohort_screen.dart:57:23)
I do not want to put that logic in build
method as build
could be called multiple times and the initialization needs to happen only once. I could put the entire logic in a block with a boolean isInitialized flag, but that does not seem like the right way of doing this. Is this requirement/case not supported in flutter as of now?
ModalRoute. of is used to build the route after it has been pushed in the navigation history.
A route that blocks interaction with previous routes. ModalRoutes cover the entire Navigator. They are not necessarily opaque, however; for example, a pop-up menu uses a ModalRoute but only shows the menu in a small box overlapping the previous route. The T type argument is the return value of the route.
pushNamed() method, we need to define the route name. After getting the route name, flutter knows which screen (widget) it needs to build. Navigator.pushNamed() sample code.
use MaterialApp.onGenerateRoute
property like this:
onGenerateRoute: (RouteSettings settings) { print('build route for ${settings.name}'); var routes = <String, WidgetBuilder>{ "hello": (ctx) => Hello(settings.arguments), "other": (ctx) => SomeWidget(), }; WidgetBuilder builder = routes[settings.name]; return MaterialPageRoute(builder: (ctx) => builder(ctx)); },
now you can simply use NavigatorState.pushNamed
:
Navigator.of(context).pushNamed("hello", arguments: "world");
here you have some test Hello
widget:
class Hello extends StatelessWidget { final String greet; Hello(this.greet); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Center( child: Text( 'hello $greet', textScaleFactor: 5.0, ), ), ); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With