如何在数据实时更新的 Flutter 中将 Future 转换为 Stream
How to convert a Future to Stream in Flutter where data updates in real time
我有一个 Future 方法 (getUserProfileData),用于检索用户 post 的数量、关注者的数量、用户名、个人资料图像等。它非常适合一次性检索数据。如果用户添加 post 我希望 UI 上的 post 数量实时更新,而无需导航到新页面并返回刷新 UI.我查看了不同的 SO 线程,阅读了文档,Firestore 运行良好。问题是我的经验水平有限,因此很难弄清楚如何重构我的代码以获得我正在寻找的行为。我已经删除了填充、容器和其他布局代码以缩短提交的代码。任何帮助将不胜感激。
class ProfileTabExample extends StatefulWidget {
const ProfileTabExample({
Key? key,
required this.profileID,
required this.userProfileKey,
}) : super(key: key);
final String profileID;
final Key userProfileKey;
@override
State<ProfileTabExample> createState() => _ProfileTabExampleState();
}
class _ProfileTabExampleState extends State<ProfileTabExample> {
Map<String, dynamic> userData = {};
int postLength = 0;
int followers = 0;
int following = 0;
bool isFollowing = false;
bool isLoading = false;
final String currentUser = Auth().currentUser?.uid as String;
@override
void initState() {
super.initState();
_getUserProfileData();
}
Future _getUserProfileData() async {
setState(() {
isLoading = true;
});
try {
DocumentSnapshot<Map<String, dynamic>> userSnap = await FirebaseFirestore
.instance
.collection('users')
.doc(widget.profileID)
.get();
QuerySnapshot<Map<String, dynamic>> postSnap = await FirebaseFirestore
.instance
.collection('posts')
.where('userID', isEqualTo: Auth().currentUser?.uid)
.get();
postLength = postSnap.docs.length;
userData = userSnap.data() as Map<String, dynamic>;
followers = userData['followers'].length;
following = userData['following'].length;
isFollowing = userData['followers'].contains(Auth().currentUser?.uid);
setState(() {});
} catch (e) {
SnackBarUtil.showSnackBar(
context,
e.toString(),
);
}
setState(() {
isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return isLoading
? const AdaptiveCircularProgress()
: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
ProfileStatColumn(
count: postLength,
label: ProfilePageString.posts,
),
ProfileStatColumn(
count: followers,
label: ProfilePageString.followers,
),
ProfileStatColumn(
count: following,
label: ProfilePageString.following,
),
],
),
),
],
);
}
}
snapshots method provides stream
, which notifies about changes. Use StreamBuilder 重建小部件。
像这样:
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('posts').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
...
},
);
我有一个 Future 方法 (getUserProfileData),用于检索用户 post 的数量、关注者的数量、用户名、个人资料图像等。它非常适合一次性检索数据。如果用户添加 post 我希望 UI 上的 post 数量实时更新,而无需导航到新页面并返回刷新 UI.我查看了不同的 SO 线程,阅读了文档,Firestore 运行良好。问题是我的经验水平有限,因此很难弄清楚如何重构我的代码以获得我正在寻找的行为。我已经删除了填充、容器和其他布局代码以缩短提交的代码。任何帮助将不胜感激。
class ProfileTabExample extends StatefulWidget {
const ProfileTabExample({
Key? key,
required this.profileID,
required this.userProfileKey,
}) : super(key: key);
final String profileID;
final Key userProfileKey;
@override
State<ProfileTabExample> createState() => _ProfileTabExampleState();
}
class _ProfileTabExampleState extends State<ProfileTabExample> {
Map<String, dynamic> userData = {};
int postLength = 0;
int followers = 0;
int following = 0;
bool isFollowing = false;
bool isLoading = false;
final String currentUser = Auth().currentUser?.uid as String;
@override
void initState() {
super.initState();
_getUserProfileData();
}
Future _getUserProfileData() async {
setState(() {
isLoading = true;
});
try {
DocumentSnapshot<Map<String, dynamic>> userSnap = await FirebaseFirestore
.instance
.collection('users')
.doc(widget.profileID)
.get();
QuerySnapshot<Map<String, dynamic>> postSnap = await FirebaseFirestore
.instance
.collection('posts')
.where('userID', isEqualTo: Auth().currentUser?.uid)
.get();
postLength = postSnap.docs.length;
userData = userSnap.data() as Map<String, dynamic>;
followers = userData['followers'].length;
following = userData['following'].length;
isFollowing = userData['followers'].contains(Auth().currentUser?.uid);
setState(() {});
} catch (e) {
SnackBarUtil.showSnackBar(
context,
e.toString(),
);
}
setState(() {
isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return isLoading
? const AdaptiveCircularProgress()
: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
ProfileStatColumn(
count: postLength,
label: ProfilePageString.posts,
),
ProfileStatColumn(
count: followers,
label: ProfilePageString.followers,
),
ProfileStatColumn(
count: following,
label: ProfilePageString.following,
),
],
),
),
],
);
}
}
snapshots method provides stream
, which notifies about changes. Use StreamBuilder 重建小部件。
像这样:
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('posts').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
...
},
);