StreamBuilder 子更新在导航后不呈现
StreamBuilder child update not rendering after navigation
我正在使用 flutter 的 StreamBuilder
来决定向用户显示哪个“根”页面。现在基本上有 2 种可能性 - LoginPage
或 HomePage
。我的应用程序的主要构建方法如下所示:
Widget build(BuildContext context) => StreamProvider.value(
initialData: CurrentUser.initial,
value: AuthService().user,
child: Consumer<CurrentUser>(
builder: (context, currentUser, _) => MaterialApp(
home: currentUser.isInitialValue
? Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
)
: currentUser.user != null
? MultiProvider(providers: [
Provider<User>.value(value: currentUser.user),
// NOTE: Any other user-bound providers here can be added here
], child: HomePage())
: LoginPage())));
登录页面的相关部分是它为您提供了两个选项:
- “您是新用户吗”- 注册
- “你回来了吗”- 登录
当您单击其中一个按钮时,您将通过导航器以特定模式转到表单:
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => LoginPage(
mode: LoginPageMode.signUp,
),
))
成功登录或注册后,流会更新并呈现 HomePage
。我知道这一点是因为我在构建方法中有一个打印语句 ("Building HomePage"
):
class HomePage extends StatelessWidget {
const HomePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
print('Building HomePage');
return Scaffold(
body: Container(
alignment: Alignment.center,
child: Text('HOME'),
));
}
}
然而,屏幕实际上并没有改变。屏幕保留在登录页面上。我认为我可以很好地管理流,因为如果我不这样做,渲染方法将永远不会被命中。我看到了一个类似的问题 ,但他们似乎没有正确管理流。我怎样才能看到渲染方法命中,但屏幕保持不变?我使用 Flutter 已经有一段时间了,但我以前从未见过它。
我认为这与导航有关,因为如果我删除用户选择“登录”或“注册”的步骤,然后将他们发送到登录页面,问题就会消失。这就像 HomePage
正在导航到的页面下构建。
1。说明
这种行为的原因是您使用根导航器在应用程序根级别推送 LoginPage
路由。这是小部件树显示推送后的小部件关系:
App
|
|-- StreamBuilder
| |--LoginPage()
|
|-- LoginPage(mode: LoginPageMode.signUp)
因此,当您的 StreamBuilder 更改数据时,树会变成这样:
App
|
|-- StreamBuilder
| |--HomePage() // <--- CHANGED
|
|-- LoginPage(mode: LoginPageMode.signUp)
这就是为什么您仍然看到 LoginPage
并且同时 HomePage
也被渲染的原因。 HomePage
就在 LoginPage
.
的“下方”
2。解决方案
解决方法是使用嵌套导航器:
Widget build(BuildContext context) => StreamProvider.value(
initialData: CurrentUser.initial,
value: AuthService().user,
child: Consumer<CurrentUser>(
builder: (context, currentUser, _) => MaterialApp(
home: currentUser.isInitialValue
? Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
)
: currentUser.user != null
? MultiProvider(providers: [
Provider<User>.value(value: currentUser.user),
// NOTE: Any other user-bound providers here can be added here
], child: HomePage())
: Navigator( // <--- HERE
onGenerateRoute: (settings) {
return CupertinoPageRoute(
builder: (context) => LoginPage(),
);
},
)));
...
在这种情况下,当您在 LoginPage
中调用 Navigator.push(context, ...)
时,您的小部件树将如下所示:
App
|
|-- StreamBuilder
|-- Navigator()
|-- LoginPage()
|-- LoginPage(mode: LoginPageMode.signUp)
请尝试此方法,它应该有效。
我正在使用 flutter 的 StreamBuilder
来决定向用户显示哪个“根”页面。现在基本上有 2 种可能性 - LoginPage
或 HomePage
。我的应用程序的主要构建方法如下所示:
Widget build(BuildContext context) => StreamProvider.value(
initialData: CurrentUser.initial,
value: AuthService().user,
child: Consumer<CurrentUser>(
builder: (context, currentUser, _) => MaterialApp(
home: currentUser.isInitialValue
? Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
)
: currentUser.user != null
? MultiProvider(providers: [
Provider<User>.value(value: currentUser.user),
// NOTE: Any other user-bound providers here can be added here
], child: HomePage())
: LoginPage())));
登录页面的相关部分是它为您提供了两个选项:
- “您是新用户吗”- 注册
- “你回来了吗”- 登录
当您单击其中一个按钮时,您将通过导航器以特定模式转到表单:
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => LoginPage(
mode: LoginPageMode.signUp,
),
))
成功登录或注册后,流会更新并呈现 HomePage
。我知道这一点是因为我在构建方法中有一个打印语句 ("Building HomePage"
):
class HomePage extends StatelessWidget {
const HomePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
print('Building HomePage');
return Scaffold(
body: Container(
alignment: Alignment.center,
child: Text('HOME'),
));
}
}
然而,屏幕实际上并没有改变。屏幕保留在登录页面上。我认为我可以很好地管理流,因为如果我不这样做,渲染方法将永远不会被命中。我看到了一个类似的问题
我认为这与导航有关,因为如果我删除用户选择“登录”或“注册”的步骤,然后将他们发送到登录页面,问题就会消失。这就像 HomePage
正在导航到的页面下构建。
1。说明
这种行为的原因是您使用根导航器在应用程序根级别推送 LoginPage
路由。这是小部件树显示推送后的小部件关系:
App
|
|-- StreamBuilder
| |--LoginPage()
|
|-- LoginPage(mode: LoginPageMode.signUp)
因此,当您的 StreamBuilder 更改数据时,树会变成这样:
App
|
|-- StreamBuilder
| |--HomePage() // <--- CHANGED
|
|-- LoginPage(mode: LoginPageMode.signUp)
这就是为什么您仍然看到 LoginPage
并且同时 HomePage
也被渲染的原因。 HomePage
就在 LoginPage
.
2。解决方案
解决方法是使用嵌套导航器:
Widget build(BuildContext context) => StreamProvider.value(
initialData: CurrentUser.initial,
value: AuthService().user,
child: Consumer<CurrentUser>(
builder: (context, currentUser, _) => MaterialApp(
home: currentUser.isInitialValue
? Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
)
: currentUser.user != null
? MultiProvider(providers: [
Provider<User>.value(value: currentUser.user),
// NOTE: Any other user-bound providers here can be added here
], child: HomePage())
: Navigator( // <--- HERE
onGenerateRoute: (settings) {
return CupertinoPageRoute(
builder: (context) => LoginPage(),
);
},
)));
...
在这种情况下,当您在 LoginPage
中调用 Navigator.push(context, ...)
时,您的小部件树将如下所示:
App
|
|-- StreamBuilder
|-- Navigator()
|-- LoginPage()
|-- LoginPage(mode: LoginPageMode.signUp)
请尝试此方法,它应该有效。