如何在数据实时更新的 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) {
...
  },
);