Kyaw Tun Kyaw Tun - 1 year ago 107
Dart Question

Flutter : How to navigate to new page after state change?

How to navigate to new page after state change?

I had an app that require login first. Only after login, the app component are fully created. So I wrote something like this:

Main app

class AppComponentState extends State<AppComponent> implements CredentialProvider {

Credential credential;

@override
Widget build(BuildContext context) {
if (credential == null) {
return new MaterialApp(
routes: <String, WidgetBuilder>{
'/': (BuildContext context) => new LoginPage(this),
},
);
} else {
return new MaterialApp(
routes: <String, WidgetBuilder>{
'/': (BuildContext context) => new Desktop(credential),
...
},
);
}
}
@override
void setCredential(Credential s) {
setState(() {
credential = s;
});
}
}


Credential provider interface

abstract CredentialProvider {
void setCredential(Credential c);
}


The login button listener in
LoginPage
, credential is set and route to the new page.

@override
Widget build(BuildContext context) {

void _handleSubmitted() {
...
credentialProvider.setCredential(c); // this change main widget state and hence new pages are created
// call setTimeout ?
Navigator.pushNamed(context, "/"); // this should go to new page, because credential is set.
}

...
}


It seem like, I have to wait current digest loop to finish before invoking
Navigator.pushNamed(context, "/");
. Is there any good way to do in flutter digest cycle like
setTimeout
in javascript?

It is a bit weird, conditional creation of
MaterialApp
. Is there better pattern in flutter?

Answer Source

To answer your direct question, addPostFrameCallback or Future.delayed can call code after a minimal delay. However, there are some issues with this pattern:

  • I would recommend that you only have one MaterialApp widget. You can have a separate route for the login page.
  • In Flutter, state flows from parent to child. Children should not be calling methods on parent State. Instead the parent can pass callbacks to the children. Or perhaps a ChangeNotifier. If there's no other way to do what you want, you could use a GlobalKey to get access to the AppComponentState from any place in the app and call setCredential on it, but you're losing some encapsulation and testability by doing so.
  • Pushing another "/" on the navigator stack might cause issues if the user presses the back button and goes back to the previous place. Probably what you want is to trigger a rebuild of some widget that is a parent of LoginPage and Desktop. Or you can call runApp() again to force everything to rebuild.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download