我有一个带有底部导航栏的屏幕:
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);
},
),
],
),
),
),
),
],
),
),
),
);
}
}