Flutter/Firebase:如何减少对推送/弹出调用的 StreamBuilder 调用?

Posted

技术标签:

【中文标题】Flutter/Firebase:如何减少对推送/弹出调用的 StreamBuilder 调用?【英文标题】:Flutter/Firebase: How to reduce StreamBuilder call on push/pop call? 【发布时间】:2021-07-17 09:44:15 【问题描述】:

我有一个带有底部导航栏的屏幕:

class AttendantMainPage extends StatefulWidget 
  final String? email;

  AttendantMainPage(
    Key? key,
    this.email,
  ) : super(key: key);

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


class _AttentdantMainPageState extends State<AttendantMainPage> 
  var user = FirebaseAuth.instance.currentUser;
  int _currentIndex = 1;
  late final List<Widget> _children;

  @override
  void initState() 
    _children = [
      ProfilePage(),
      AttendantHomePage(),
      ChatListPage(),
    ];
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        backgroundColor: Colors.white,
        selectedItemColor: Color(0xffe96cbd),
        onTap: onTabPressed,
        currentIndex: _currentIndex,
        items: [
          BottomNavigationBarItem(
              icon: new Icon(
                CustomIcons.user,
              ),
              label: 'Profile'),
          BottomNavigationBarItem(
              icon: new Icon(
                CustomIcons.home,
              ),
              label: 'Home'),
          BottomNavigationBarItem(
              icon: new Icon(
                Icons.mail,
              ),
              label: 'Messages'),
        ],
      ),
    );
  

  void onTabPressed(int index) 
    setState(() 
      _currentIndex = index;
    );
  


我在所有屏幕中都有 streamBuilder。当我更改屏幕时,我的流构建器被一次又一次地调用。我猜使用firebase可能真的很贵。这是其中一个屏幕的代码,有人可以告诉我如何避免在页面之间切换后不必要的调用吗?

class ProfilePage extends StatefulWidget 
  @override
  _ProfilePageState createState() => _ProfilePageState();


class _ProfilePageState extends State<ProfilePage> 
  bool enabled = false;
  late FocusNode myFocusNode;
  var user = FirebaseAuth.instance.currentUser;
  late Stream<DocumentSnapshot> stream;

  @override
  void initState() 
    stream = FirebaseFirestore.instance
        .collection('users')
        .doc(user!.uid)
        .snapshots();
    myFocusNode = FocusNode();

    super.initState();
  

  @override
  void dispose() 
    // Clean up the focus node when the Form is disposed.
    myFocusNode.dispose();
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    double _width = MyUtility(context).width;
    double _height = MyUtility(context).height;
    return Scaffold(
      backgroundColor: Color(0xfff0eded),
      body: SingleChildScrollView(
        physics: NeverScrollableScrollPhysics(),
        child: Container(
          width: _width,
          height: _height,
          child: Column(
            children: [
              Stack(
                alignment: AlignmentDirectional.topCenter,
                children: [
                  Container(
                    width: _width,
                    height: _height * 0.4,
                  ),
                  Container(
                    height: _height * 0.25,
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topRight,
                        end: Alignment.bottomLeft,
                        colors: [
                          Color(0xff4d629f),
                          Color(0xffe96cbd),
                        ],
                      ),
                    ),
                  ),
                  Positioned(
                    bottom: _height * 0.02,
                    child: ProfileImage(
                      width: _width * 0.5,
                      height: _height * 0.25,
                      userEmail: user!.email!,
                    ),
                  ),
                  Positioned(
                    right: _width * 0.25,
                    bottom: _height * 0.05,
                    child: ClipOval(
                      child: Container(
                        color: Colors.white,
                        child: Padding(
                          padding: const EdgeInsets.all(2),
                          child: ClipOval(
                            child: Material(
                              color: Color(0xffe96cbd), // button color
                              child: InkWell(
                                splashColor: Color(0xffffc2ea), // inkwell color
                                child: SizedBox(
                                    width: _width * 0.08,
                                    height: _height * 0.04,
                                    child: Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Icon(
                                        Icons.edit,
                                        color: Colors.white,
                                        size: MyUtility(context).width * 0.04,
                                      ),
                                    )),
                                onTap: () 
                                  getImage().then((value) 
                                    uploadFile(value);
                                  );
                                ,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
              Stack(
                alignment: AlignmentDirectional.topCenter,
                children: [
                  Padding(
                    padding: EdgeInsets.symmetric(
                      vertical: 10,
                      horizontal: _width * 0.05,
                    ),
                    child: OverlayPanel(
                      width: _width * 0.9,
                      child: Padding(
                        padding: EdgeInsets.all(
                          _height * 0.04,
                        ),
                        child: Column(
                          children: [
                            StreamBuilder<DocumentSnapshot>(
                                stream: stream,
                                builder: (context, snapshot) 
                                  if (snapshot.hasData) 
                                    return TextFormField(
                                      focusNode: myFocusNode,
                                      enabled: enabled,
                                      initialValue: snapshot.data!['username'],
                                      textAlign: TextAlign.center,
                                      style: TextStyle(
                                        fontSize: 30,
                                        color: Color(0xff273150),
                                      ),
                                      onFieldSubmitted: (input) 
                                        setState(() 
                                          enabled = false;
                                        );
                                        print(input);
                                        FirebaseFirestore.instance
                                            .collection('users')
                                            .doc(user!.uid)
                                            .update('username': input);
                                      ,
                                    );
                                   else
                                    return TextField(
                                      enabled: false,
                                      style: TextStyle(fontSize: 30),
                                    );
                                ),
                            SizedBox(
                              height: _height * 0.02,
                            ),
                            Text(user!.email!,
                                style: TextStyle(
                                  fontSize: 18.0,
                                  color: Color(0xff273150),
                                )),
                            Text(
                              //TODO great idea to use currentUser: user!.displayName as a user Type to check it all easier and faster
                              'Type: $'Attendant'',
                              style: TextStyle(
                                fontSize: 14.0,
                                color: Color(0xff273150),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                  Positioned(
                    right: _width * 0.1,
                    top: _height * 0.025,
                    child: ClipOval(
                      child: Container(
                        color: Colors.white,
                        child: Padding(
                          padding: const EdgeInsets.all(2),
                          child: ClipOval(
                            child: Material(
                              color: Color(0xffe96cbd), // button color
                              child: InkWell(
                                splashColor: Color(0xffffc2ea), // inkwell color
                                child: SizedBox(
                                    width: _width * 0.08,
                                    height: _width * 0.08,
                                    child: Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Icon(
                                        Icons.edit,
                                        color: Colors.white,
                                        size: _width * 0.04,
                                      ),
                                    )),
                                onTap: () async 
                                  setState(() 
                                    enabled = !enabled;
                                  );
                                  await Future.delayed(
                                      Duration(milliseconds: 10),
                                      () => 
                                            FocusScope.of(context)
                                                .requestFocus(myFocusNode),
                                          );
                                ,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 10.0),
                child: Container(
                  width: _width,
                  decoration: BoxDecoration(
                    color: Color(0xfff0eded),
                  ),
                  child: Container(
                    child: Column(
                      children: [
                        CustomButton(
                          width: _width * 0.9,
                          icon: Icons.lock,
                          text: 'Change Password',
                          onPressed: () 
                            //TODO add possibility to change password
                          ,
                        ),
                        CustomButton(
                          width: _width * 0.9,
                          icon: Icons.delete,
                          text: 'Delete Account',
                          onPressed: () ,
                        ),
                        CustomButton(
                          width: _width * 0.9,
                          icon: Icons.logout,
                          text: 'Log Out',
                          onPressed: () async 
                            await FirebaseAuth.instance.signOut();
                            Navigator.pop(context);
                          ,
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  

【问题讨论】:

看来您需要保持页面活动,只需检查提供的链接。我认为可能会回答您的问题。 ***.com/questions/50883918/… 谢谢兄弟!使用IndexedStack 解决了我的问题 很高兴它对你有用。 【参考方案1】:

在我的AttendantMainPage 中更改身体来自:

  body: _children[_currentIndex],

   body: IndexedStack(
        index: _currentIndex,
        children: _children,
      ),

解决了这个问题。

感谢大家的帮助!

【讨论】:

以上是关于Flutter/Firebase:如何减少对推送/弹出调用的 StreamBuilder 调用?的主要内容,如果未能解决你的问题,请参考以下文章

如果应用程序未启动,Flutter Firebase 推送通知无法数据

Flutter firebase 消息推送通知格式 3 行

Flutter Firebase前台推送通知未显示但后台正在运行

Flutter Firebase如何控制通知在应用程序处于前台时不显示

如何在 Flutter Firebase 应用中搜索并向附近的人发送通知?

flutter firebase 如何获取节点的所有子节点