Issue
Can I navigate to another widget when the first one is being built?
The following assertion was thrown building Navigator-[GlobalObjectKey<NavigatorState> _WidgetsAppState#1d8fb](dirty, state: NavigatorState#999bc(tickers: tracking 2 tickers)):
im trying to demonstrate how to navigate from one screen to another without pressing any buttons, i mean if im at a certain screen it will load the other screen after a few seconds without me doing anything, however when i put the navigator outside the build method and call it with initState it gives me an error. heres my code
class Screen0 extends StatefulWidget {
@override
_Screen0State createState() => _Screen0State();
}
class _Screen0State extends State<Screen0> {
@override
void initState() {
changeScreen();
super.initState();
}
void changeScreen() {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return MyHomePage(title: 'Flutter Demo Home Page');
}));
}
@override
Widget build(BuildContext context) {
return Scaffold();
}
}
--------------------- my other screen -----------------------------
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
i fixed it using this code for the navigator in the changeScreen method:
Future(() {
Navigator.push(
context, MaterialPageRoute(builder: (context) => CityScreen()));
});
thank you all for your help!
Solution
You need to understand a little bit more about the lifecycle of a widget in Flutter. When the initState is called the framework is busy rendering the widget to the widgets tree. All its doing in the initState is that its collecting information that might be needed to render the widgets in a certain way.
What you are doing by calling changeScreen()
in the initState is, you are telling flutter to build another widget when its already building one. Which gives an error.
Only when the first widget is built, you can Navigate to(or Build) another widget.
Now let's talk about how you can accomplish what you are trying to do.
You want to navigate to another widget after a fraction of second, once the main screen is built.
You need to let flutter render its main widget (whose initState you want to edit) and only then tell it to navigate to another widget.
Change your changeScreen()
function like this:
changeRoute() async {
await Future.delayed(Duration(seconds: 1), () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
});
}
What happens here, is that the event loop waits for 1 second (defined by us in the Future.delayed method) and then everything in changeScreen()
happens. By the end of that 1 second, flutter renders its main widget and looks for whats left. Whats left? our changeScreen()
!!
Hence, right after one second. The screen Navigates.
PS: This answer might be debatable as we don't know how much time flutter will take to render the main widget. If it takes more than one second (very rare), then the error will persist.
Answered By - Yudhishthir Singh
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.