Flutter:状态更改后如何导航到新页面?
Flutter : How to navigate to new page after state change?
状态改变后如何导航到新页面?
我有一个需要先登录的应用程序。只有登录后,应用程序组件才会完全创建。所以我写了这样的东西:
主应用程序
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;
});
}
}
凭据提供程序接口
abstract CredentialProvider {
void setCredential(Credential c);
}
LoginPage
中的登录按钮侦听器,已设置凭据并路由到新页面。
@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.
}
...
}
看来,我必须等待当前 digest loop 完成才能调用 Navigator.pushNamed(context, "/");
。在 javascript 中的 setTimeout
之类的 flutter digest cycle 中有什么好的方法吗?
有点奇怪,MaterialApp
的条件创建。颤振有更好的模式吗?
为了回答您的直接问题,addPostFrameCallback
or Future.delayed
可以在最短延迟后调用代码。但是,此模式存在一些问题:
- 我建议您只使用一个
MaterialApp
小部件。您可以为登录页面设置单独的路由。
- 在 Flutter 中,状态从 parent 流向 child。 Children 不应在 parent
State
上调用方法。相反,parent 可以将回调传递给 children。或者可能是 ChangeNotifier
. If there's no other way to do what you want, you could use a GlobalKey
从应用程序中的任何位置访问 AppComponentState
并对其调用 setCredential
,但这样做会失去一些封装性和可测试性。
- 如果用户按下后退按钮并返回到之前的位置,则在导航器堆栈上推送另一个
"/"
可能会导致问题。可能您想要的是触发某个小部件的重建,该小部件是 LoginPage
和 Desktop
的 parent。或者您可以再次调用 runApp()
以强制 一切 重建。
状态改变后如何导航到新页面?
我有一个需要先登录的应用程序。只有登录后,应用程序组件才会完全创建。所以我写了这样的东西:
主应用程序
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;
});
}
}
凭据提供程序接口
abstract CredentialProvider {
void setCredential(Credential c);
}
LoginPage
中的登录按钮侦听器,已设置凭据并路由到新页面。
@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.
}
...
}
看来,我必须等待当前 digest loop 完成才能调用 Navigator.pushNamed(context, "/");
。在 javascript 中的 setTimeout
之类的 flutter digest cycle 中有什么好的方法吗?
有点奇怪,MaterialApp
的条件创建。颤振有更好的模式吗?
为了回答您的直接问题,addPostFrameCallback
or Future.delayed
可以在最短延迟后调用代码。但是,此模式存在一些问题:
- 我建议您只使用一个
MaterialApp
小部件。您可以为登录页面设置单独的路由。 - 在 Flutter 中,状态从 parent 流向 child。 Children 不应在 parent
State
上调用方法。相反,parent 可以将回调传递给 children。或者可能是ChangeNotifier
. If there's no other way to do what you want, you could use aGlobalKey
从应用程序中的任何位置访问AppComponentState
并对其调用setCredential
,但这样做会失去一些封装性和可测试性。 - 如果用户按下后退按钮并返回到之前的位置,则在导航器堆栈上推送另一个
"/"
可能会导致问题。可能您想要的是触发某个小部件的重建,该小部件是LoginPage
和Desktop
的 parent。或者您可以再次调用runApp()
以强制 一切 重建。