Flutter StreamBuilder子更新在导航后不渲染

Flutter StreamBuilder子更新在导航后不渲染,flutter,stream-builder,Flutter,Stream Builder,我使用Flatter的StreamBuilder来决定向用户显示哪个“根”页面。现在基本上有两种可能性-登录页面或主页。我的应用程序的主要构建方法如下所示: Widget build(BuildContext context) => StreamProvider.value( initialData: CurrentUser.initial, value: AuthService().user, child: Consumer<CurrentU

我使用Flatter的
StreamBuilder
来决定向用户显示哪个“根”页面。现在基本上有两种可能性-
登录页面
主页
。我的应用程序的主要构建方法如下所示:

  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())));
App
  |
  |-- StreamBuilder
         |-- Navigator()
              |-- LoginPage()
              |-- LoginPage(mode: LoginPageMode.signUp)

成功登录或注册后,将更新流,并呈现
主页
。我知道这一点,因为我在build方法中有一个print语句(
“Building HomePage”
):

然而,屏幕实际上并没有改变。屏幕仍保留在登录页面上。我认为我可以很好地管理流,因为如果我不是,渲染方法将永远不会被击中。我看到了一个类似的问题,但他们似乎没有正确管理流。如何才能看到渲染方法命中,而屏幕保持不变?我和弗利特一起工作有一段时间了,我以前从未见过这种情况

我认为这与导航有关,因为如果我删除用户选择“登录”或“注册”的步骤,并将其发送到登录页面,问题就会消失。这就像是在导航到的页面下构建
主页。

1。解释 这种行为的原因是您使用根导航器在应用程序根级别推送
LoginPage
route。下面是widgets树,显示推送后的widgets关系:

App
  |
  |-- StreamBuilder
  |      |--LoginPage()
  |
  |-- LoginPage(mode: LoginPageMode.signUp)

因此,当StreamBuilder更改数据时,树将变成:

App
  |
  |-- StreamBuilder
  |      |--HomePage()    // <--- CHANGED
  |
  |-- LoginPage(mode: LoginPageMode.signUp)

在这种情况下,当您调用
Navigator.push(context,…)
内部
LoginPage
时,您的小部件树将如下所示:

  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())));
App
  |
  |-- StreamBuilder
         |-- Navigator()
              |-- LoginPage()
              |-- LoginPage(mode: LoginPageMode.signUp)

请尝试这种方法,它应该会起作用。

1。解释 这种行为的原因是您使用根导航器在应用程序根级别推送
LoginPage
route。下面是widgets树,显示推送后的widgets关系:

App
  |
  |-- StreamBuilder
  |      |--LoginPage()
  |
  |-- LoginPage(mode: LoginPageMode.signUp)

因此,当StreamBuilder更改数据时,树将变成:

App
  |
  |-- StreamBuilder
  |      |--HomePage()    // <--- CHANGED
  |
  |-- LoginPage(mode: LoginPageMode.signUp)

在这种情况下,当您调用
Navigator.push(context,…)
内部
LoginPage
时,您的小部件树将如下所示:

  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())));
App
  |
  |-- StreamBuilder
         |-- Navigator()
              |-- LoginPage()
              |-- LoginPage(mode: LoginPageMode.signUp)


请尝试这种方法,它应该会起作用。

key:UniqueKey(),
添加到
MaterialApp
中确实有帮助,我一直在摆弄MaterialApp键。但是,它确实会导致一种奇怪的临时状态,在进入
主页之前,它会返回
登录页面
几秒钟。但是,如果我手动构建键
key=user==null?“user null':'${user.id}'
,它可以工作,而这种奇怪的中间状态不会发生。一个感觉不对,另一个感觉不舒服。为什么在执行build方法时不进行flatter渲染?我以为键是用来确定是否调用build,而不是用来确定是否绘制屏幕……我不知道这是
MaterialApp
widget的一个bug还是一个功能-我需要检查官方文档和源代码add
key:UniqueKey(),
to
MaterialApp
这确实有帮助,我一直在摆弄MaterialApp键。但是,它确实会导致一种奇怪的临时状态,在进入
主页之前,它会返回
登录页面
几秒钟。但是,如果我手动构建键
key=user==null?“user null':'${user.id}'
,它可以工作,而这种奇怪的中间状态不会发生。一个感觉不对,另一个感觉不舒服。为什么在执行build方法时不进行flatter渲染?我以为键是用来决定是否调用build,而不是用来决定是否绘制屏幕…我不知道这是否是
MaterialApp
widget的bug或功能-我需要检查官方文档和源代码