导航后未渲染StreamBuilder子更新 [英] StreamBuilder child update not rendering after navigation

查看:47
本文介绍了导航后未渲染StreamBuilder子更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用flutter的 StreamBuilder 来确定哪个根"显示用户的页面.现在基本上有两种可能性- LoginPage Home .我的应用程序的主要构建方法如下:

I'm using flutter's StreamBuilder to decide which "root" page to show a user. Right now there are basically 2 possibilities - LoginPage or HomePage. My app's main build method looks like this:

  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())));

登录页面的相关部分在于它为您提供了两种选择:

The relevant part of the login page is that it gives you two options:

  1. 您是新用户"吗?-注册
  2. 您是否要返回"-登录

当您单击其中一个按钮时,将通过导航器以某种模式进入表单:

When you click one of those buttons, you go to the form in a certain mode via the navigator:

Navigator.push(
                                context,
                                CupertinoPageRoute(
                                  builder: (context) => LoginPage(
                                    mode: LoginPageMode.signUp,
                                  ),
                                ))

成功登录或注册后,流将更新并显示 Home .我知道这是因为在build方法("Building HomePage"" )中有一条打印语句:

After successfully logging in or signing up, the stream gets updated and the HomePage renders. I know this because I have a print statement in the build method ("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'),
    ));
  }
}

但是,屏幕实际上并没有改变.屏幕保留在登录页面上.我认为我可以很好地管理流,因为如果不这样做,将永远不会使用render方法.我在此处看到了类似的问题,但似乎他们没有在管理正常播放.我如何才能看到渲染方法命中,但屏幕保持不变?我已经与Flutter合作了一段时间,但之前从未见过.

However, the screen does not actually change. The screen remains on the login page. I think I'm managing the stream fine because if I wasn't the render method would never be hit. I saw a similar question here but it seems they are not managing the stream properly. How can I see the render method hit, yet the screen stay the same? I've been working with Flutter for a while and I've never seen this before.

我认为这与导航有关,因为如果我删除了用户选择登录"的步骤,或注册",然后我将其发送到登录页面,问题就消失了.就像 Home 是在导航到的页面下构建的.

I think it has something to do with the navigation because if I remove the step where the user chooses "sign in" or "sign up", and I just send them to the sign in page, the issue disappears. It's like the HomePage is being built under the page that was navigated to.

推荐答案

1.说明

这种行为的原因是您使用root导航器在应用程序根级别上推送了 LoginPage 路由.这是小部件树,显示了推送后的小部件关系:

1. Explanation

The reason of such behavior is that you use root Navigator that pushes LoginPage route on the apps root level. Here is widgets tree reveals widgets relations after push:

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

因此,当您的StreamBuilder更改数据时,树将变为:

So when your StreamBuilder changes data the tree becomes this:

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

这就是为什么您仍然看到 LoginPage 以及同时呈现 HomePage 的原因. Home 只是位于下方" LoginPage .

Thats why you still see LoginPage and at the same time HomePage rendered too. HomePage just lays "under" LoginPage.

解决方案是使用嵌套导航器:

The solution is to use nested Navigator:


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,...)时,小部件树将如下所示:

In that case when you will call Navigator.push(context, ...) inside LoginPage your widget tree will look like this:

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

请尝试这种方法,它应该可以工作.

Please try this approach, it should work.

这篇关于导航后未渲染StreamBuilder子更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆