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

问题描述

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

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,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,Positioned(
                    right: _width * 0.1,top: _height * 0.025,height: _width * 0.08,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: () {},icon: Icons.logout,text: 'Log Out',onpressed: () async {
                            await FirebaseAuth.instance.signOut();
                            Navigator.pop(context);
                          },);
  }
}

解决方法

更改我的 AttendantMainPage 中的正文:

  body: _children[_currentIndex],

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

解决了问题。

感谢大家的帮助!