多页面使用StreamBuilder访问Firestore流仅单页生效问题求助
问题解决:IndexedStack中两个页面共享Firestore Stream仅一个加载的问题
核心原因
你的FirestoreService中,userStream是一个getter方法,每次调用都会返回一个全新的Firestore snapshots()流。当IndexedStack同时初始化两个页面时,两个页面会分别订阅独立的流,这可能导致Firestore SDK出现订阅竞争,其中一个流无法正常接收数据更新。
解决方案
修改FirestoreService,将userStream改为实例变量,确保所有页面共享同一个流订阅:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; class FirestoreService { final Stream<DocumentSnapshot> userStream; FirestoreService() { final userUid = FirebaseAuth.instance.currentUser!.uid; userStream = FirebaseFirestore.instance.collection('users').doc(userUid).snapshots(); } }
额外优化(可选)
移除页面initState中存储firestoreService的代码,直接在StreamBuilder中通过Provider获取服务,更符合Provider的最佳实践:
以DashboardPage为例:
// 移除initState中的代码 // late FirestoreService firestoreService; // @override // void initState() { // super.initState(); // firestoreService = Provider.of<FirestoreService>(context, listen: false); // } @override Widget build(BuildContext context) { var screenSize = MediaQuery.of(context).size; return SingleChildScrollView( child: Center( child: Column( children: [ // ... 其他代码 StreamBuilder<DocumentSnapshot>( stream: Provider.of<FirestoreService>(context).userStream, builder: (context, snapshot){ // ... 原有的builder逻辑 } ), // ... 其他代码 ], ), ), ); }
ProfilePage做同样的修改即可。
原理说明
通过将userStream改为实例变量,FirestoreService初始化时只会创建一次流订阅,两个页面共享同一个流。这样Firestore SDK只会向这个流推送数据更新,两个页面的StreamBuilder都能正常接收并处理数据,避免了多订阅竞争导致的加载异常。
内容的提问来源于stack exchange,提问作者Lincoln Clarke
相关产品推荐
相关产品推荐

