【问题标题】:Flutter screen navigating back when updating firestore document更新 Firestore 文档时颤振屏幕导航回来
【发布时间】:2020-01-14 20:50:34
【问题描述】:

我已经使用 StreamBuilder 在 ListView 中成功显示了用户列表。但是当我在 Firestore 中更新用户文档时,我的移动应用程序中的屏幕会自动返回。

这是我的屏幕流程。登录 -> 主页 -> 管理用户 -> 用户详细信息。 通过使用下面的代码,我在管理用户屏幕中创建了一个列表。现在我正在尝试在 firebase 控制台中更新用户名。更新数据后,ManageUsers 屏幕正在关闭。 Screen Rec

Widget build(BuildContext context) {
    return new StreamBuilder(
      stream: Firestore.instance.collection('users').snapshots(),
      builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (!snapshot.hasData)
          return Center(
            child: CircularProgressIndicator(),
          );
        if (snapshot.hasError)
          return Center(child: new Text('Error: ${snapshot.error}'));
        final int itemsCount = snapshot.data.documents.length;
        switch (snapshot.connectionState) {
          case ConnectionState.none:
            // TODO: Handle this case.
            return new CircularProgressIndicator();
            break;
          case ConnectionState.waiting:
            // TODO: Handle this case.
            return new CircularProgressIndicator();
            break;
          default:
            return new ListView.builder(
              scrollDirection: Axis.vertical,
              shrinkWrap: true,
              itemCount: itemsCount,
              addAutomaticKeepAlives: true,
              itemBuilder: (BuildContext context, int index) {
                final DocumentSnapshot document =
                    snapshot.data.documents[index];

                return new ListTile(
                  title: new Text(document['first_name']),
                  subtitle: new Text(document['last_name']),
                  onTap: () => {openUserDetailsScreen(document, context)},
                );
              },
            );
        }
      },
    );
  }

实际上它应该在同一个屏幕中刷新数据,而不是向后导航。我在构建列表时做错了什么吗?

主屏幕代码

class HomeScreen extends StatefulWidget {
  HomeScreen({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomeScreenState createState() => _MyHomeScreenState();

}

class _MyHomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        automaticallyImplyLeading: false,
        leading: Builder(
          builder: (context) =>
              IconButton(
                icon: new Icon(Icons.menu),
                onPressed: () => Scaffold.of(context).openDrawer(),
              ),
        ),
      ),
      drawer: MyDrawer(widget.title),
      body: Center(
        child: Text("Home Screen"),
      ),
    );
  }

  @override
  void initState() {
    print('in home page ${globals.loggedInUser.firstName}');
  }
}

从主页我通过抽屉导航到 ManageUsers 屏幕。这是抽屉的代码。

class MyDrawer extends StatelessWidget {
  MyDrawer(this.currentPage);

  final String currentPage;

  bool isAdmin = true;

  @override
  Widget build(BuildContext context) {
    var currentDrawer = Provider.of<DrawerStateInfo>(context).getCurrentDrawer;
    return Drawer(
      child: ListView(
        children: <Widget>[
          _CustomListTile(
              currentPage, globals.HOME_MENU_TITLE, currentDrawer),
          _CustomListTile(
              currentPage, globals.LOGIN_MENU_TITLE, currentDrawer),
          ConditionalBuilder(
            condition: isAdmin,
            builder: (context) => _CustomListTile(currentPage,
                globals.MANAGE_USERS_MENU_TITLE, currentDrawer),
          )
        ],
      ),
    );
  }
}

class _CustomListTile extends StatelessWidget {
  final String currentPage;
  final String tileTitle;
  final currentDrawer;

  _CustomListTile(this.currentPage, this.tileTitle, this.currentDrawer);

  @override
  Widget build(BuildContext context) {
    return ListTile(
        title: Text(
          tileTitle,
          style: currentDrawer == 1
              ? TextStyle(fontWeight: FontWeight.bold)
              : TextStyle(fontWeight: FontWeight.normal),
        ),
        onTap: () {
          Navigator.of(context).pop();
          if (this.currentPage == tileTitle) return;
          Provider.of<DrawerStateInfo>(context).setCurrentDrawer(1);

          switch (tileTitle) {
            case globals.HOME_MENU_TITLE:
              {
                Navigator.of(context).pushReplacement(MaterialPageRoute(
                    builder: (BuildContext context) => HomeScreen(
                          title: globals.HOME_MENU_TITLE,
                        )));
                break;
              }

            case globals.LOGIN_MENU_TITLE:
              {
                Navigator.of(context).pushReplacement(MaterialPageRoute(
                    builder: (BuildContext context) => LoginScreen(
                          title: globals.LOGIN_MENU_TITLE,
                        )));
                break;
              }

            case globals.MANAGE_USERS_MENU_TITLE:
              {
                Navigator.of(context).pushNamed("/ManageUsers");
                break;
              }
            default:
              {
                break;
              }
          }
        });
  }
}

【问题讨论】:

  • 你是如何在这个流程中导航的,你是在推入导航器吗?
  • @haroldolivieri 我正在使用 pushNamed Navigator.of(context).pushNamed("/ManageUsers");
  • 可以在首页提供代码吗?
  • 我在我的问题中添加了代码。我正在通过抽屉导航到 ManageUsers 屏幕。我还为此添加了代码。

标签: flutter dart navigation-drawer


【解决方案1】:

ListView StreamBuilder 意味着它会监听你的集合。 当您移动到下一个屏幕时,请移除监听器。

【讨论】:

    【解决方案2】:

    这段代码在我看来是错误的:

    Provider.of<DrawerStateInfo>(context).setCurrentDrawer(1);
    

    你应该有类似枚举甚至 tileTitle 之类的东西来用作抽屉上当前选定选项的保存状态,否则,你只知道有一个选定的选项,但不知道是哪个选项。

    这会导致你调用错误路由的这种疯狂行为。

    试试这样的

    class MyDrawer extends StatelessWidget {
      MyDrawer(this.currentPage);
    
      final String currentPage;
    
      bool isAdmin = true;
    
      @override
      Widget build(BuildContext context) {
        return Drawer(
          child: ListView(
            children: <Widget>[
              _CustomListTile(currentPage, globals.HOME_MENU_TITLE),
              _CustomListTile(currentPage, globals.LOGIN_MENU_TITLE),
              isAdmin
                  ? _CustomListTile(currentPage, globals.MANAGE_USERS_MENU_TITLE)
                  : Container(),
            ],
          ),
        );
      }
    }
    
    class _CustomListTile extends StatelessWidget {
      final String currentPage;
      final String tileTitle;
    
      _CustomListTile(
        this.currentPage,
        this.tileTitle,
      );
    
      @override
      Widget build(BuildContext context) {
        return Consumer<DrawerStateInfo>(
          builder: (context, draweStateInfo, _) {
    
            final currentSelectedItem = draweStateInfo.getCurrentDrawer();
    
            return ListTile(
                title: Text(
                  tileTitle,
                  style: currentSelectedItem == tileTitle
                      ? TextStyle(fontWeight: FontWeight.bold)
                      : TextStyle(fontWeight: FontWeight.normal),
                ),
                onTap: () {
                  Navigator.of(context).pop();
    
                  if (currentSelectedItem == tileTitle) return;
                  draweStateInfo.setCurrentDrawer(tileTitle);
    
                  switch (currentSelectedItem) {
                    case globals.HOME_MENU_TITLE:
                      {
                        Navigator.of(context).pushReplacement(MaterialPageRoute(
                            builder: (BuildContext context) => HomeScreen(
                              title: globals.HOME_MENU_TITLE,
                            )));
                        break;
                      }
    
                    case globals.LOGIN_MENU_TITLE:
                      {
                        Navigator.of(context).pushReplacement(MaterialPageRoute(
                            builder: (BuildContext context) => LoginScreen(
                              title: globals.LOGIN_MENU_TITLE,
                            )));
                        break;
                      }
    
                    case globals.MANAGE_USERS_MENU_TITLE:
                      {
                        Navigator.of(context).pushNamed("/ManageUsers");
                        break;
                      }
                    default:
                      {
                        break;
                      }
                  }
                });
          },
        );
      }
    }
    

    【讨论】:

    • 我的代码有问题。由于我是 Flutter 新手,因此我正在学习一些随机教程。我在某个地方遇到了这个问题。现在我修改了我的代码,所以现在一切正常。
    • 但是现在你正确地保存了当前的抽屉?
    猜你喜欢
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 2018-11-26
    相关资源
    最近更新 更多