Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: Get passed arguments from Navigator in Widget's state's initState

Tags:

flutter

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?

like image 901
adarsh Avatar asked May 22 '19 18:05

adarsh


People also ask

What is the purpose of ModalRoute of ()?

ModalRoute. of is used to build the route after it has been pushed in the navigation history.

How do you use modal route in flutter?

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.

What is pushNamed in flutter?

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.


1 Answers

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,         ),       ),     );   } } 
like image 125
pskink Avatar answered Oct 09 '22 14:10

pskink