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前台推送通知未显示但后台正在运行
Flutter Firebase如何控制通知在应用程序处于前台时不显示