Flutter嵌套StreamBuilder从Firestore获取关注用户帖子遇RangeError报错求助
Hey there, let's break down that annoying RangeError you're seeing and get your homepage showing those followed users' posts correctly!
What's Causing the Error?
The RangeError (index): Invalid value: Only valid value is 0: 4 happens because you're reusing the outer ListView's index variable in your inner StreamBuilders, which doesn't make sense for those queries:
- When you query a user by
uid(second StreamBuilder), Firestore will return exactly 1 document (since each user has a unique uid). But you're trying to accessdocuments[index]whereindexcould be 4 (if you follow 5 users), which is way beyond the 1-document result set. - For the posts query (third StreamBuilder), you want to show the latest 2 posts per user, but using the outer
indexhere would only ever grab one post per user (and potentially the wrong one if the index doesn't match the posts list length).
Fixed Code Implementation
Here's the corrected version of your nested StreamBuilder code, with key fixes highlighted:
StreamBuilder( stream: _firestore .collection(FOLLOW_COLLECTION) .document(widget.myuid) .collection(FOLLOWING_COLLECTION) .snapshots(), builder: (context, fir_snapshot) { if (!fir_snapshot.hasData) { return Center(child: SpinKitThreeBounce(color: Colors.white, size: 50.0,)); } else if (fir_snapshot.hasError) { return Center(child: Text("No Data", style: TextStyle(color: GlobalUniversal.purple),)); } else { return ListView.builder( physics: NeverScrollableScrollPhysics(), shrinkWrap: true, scrollDirection: Axis.vertical, itemCount: fir_snapshot.data.documents.length, itemBuilder: (context, index) { DocumentSnapshot myfollowing = fir_snapshot.data.documents[index]; return StreamBuilder( stream: _firestore .collection(USERS_COLLECTION) .where('uid', isEqualTo: myfollowing['uid']) .snapshots(), builder: (context, sec_snapshot) { if (!sec_snapshot.hasData) { return Center(child: SpinKitThreeBounce(color: Colors.white, size: 50.0,)); } else if (sec_snapshot.hasError) { return Center(child: Text("No Data", style: TextStyle(color: GlobalUniversal.purple),)); } else { // Fix 1: Grab the first (and only) user document from the query DocumentSnapshot user = sec_snapshot.data.documents[0]; return StreamBuilder( stream: _firestore .collection(USERS_COLLECTION) .document(user.documentID) .collection(POSTS_COLLECTION) .orderBy('date', descending: true) .limit(2) // Add limit(2) to only fetch latest 2 posts .snapshots(), builder: (context, thir_snapshot) { if (!thir_snapshot.hasData) { return Center(child: SpinKitThreeBounce(color: Colors.white, size: 50.0,)); } else if (thir_snapshot.hasError) { return Center(child: Text("No Data", style: TextStyle(color: GlobalUniversal.purple),)); } else { // Fix 2: Loop through the latest 2 posts instead of using outer index return Column( children: thir_snapshot.data.documents.map((post) { int usefulCount = post['Usefuls']; int likeCount = post['Likes']; int commentCount = post['Comments']; return Padding( padding: EdgeInsets.only(top: 10.0, bottom: 10.0), child: InkWell( onTap: () { // Your navigation logic here }, child: Container( decoration: BoxDecoration( color: GlobalUniversal.whiteBG, ), child: Padding( padding: EdgeInsets.all(8.0), child: Column( children: <Widget>[ SizedBox(height: 10.0), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Padding( padding: widget.myapplang == 'ar' ? EdgeInsets.only(right: 5.0) : EdgeInsets.only(left: 5.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Container( width: 35.0, height: 35.0, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( fit: BoxFit.fill, image: NetworkImage(user['uimg']) ) ) ), SizedBox(width: 10.0), Text( '${user['name']}', style: TextStyle( color: GlobalUniversal.blackColor, fontSize: 14.0, fontWeight: FontWeight.bold, fontFamily: 'BalooDa2' ), ), ], ), ), IconButton( icon: Icon(Icons.menu, color: GlobalUniversal.blackColor), onPressed: () {} ) ], ), SizedBox(height: 20.0), Padding( padding: EdgeInsets.all(5.0), child: Text( '${post['text']}', style: TextStyle( color: GlobalUniversal.blackColor, fontSize: 16.0, fontFamily: 'Tajawal', height: 1.3 ), textAlign: TextAlign.justify, textDirection: TextDirection.rtl ), ), SizedBox(height: 15.0), Visibility( child: Text('${post['pid']}'), visible: false, ), Visibility( visible: _isVisible, child: ClipRRect( borderRadius: BorderRadius.circular(8.0), child: Image.network( post['img'] != null ? post['img'] : '', // Replace showToast with a valid placeholder fit: BoxFit.fill, ), ), ), SizedBox(height: 15.0), Divider(), Container( width: 180, height: 40, child: RaisedButton( child: Text( widget.myapplang == 'ar' ? "أكتب تعليق.." : "Write a comment..", style: TextStyle( color: GlobalUniversal.blackColor.withOpacity(0.5), fontSize: 12, fontWeight: FontWeight.bold, fontFamily: widget.myapplang == 'ar' ? 'Tajawal' : 'BalooDa2' ) ), elevation: 0.0, shape: new RoundedRectangleBorder( borderRadius: new BorderRadius.circular(25.0), ), color: GlobalUniversal.secondWhiteBG, onPressed: () async { // Your comment navigation logic here }, ), ), ], ), ), ), ), ); }).toList(), ); } }, ); } }, ); }, ); } return Container(height: 0.0, width: 0.0); }, )
Key Fixes Explained
- User Document Access: Changed
sec_snapshot.data.documents[index]tosec_snapshot.data.documents[0]since the uid query will always return exactly one user. - Post List Handling: Replaced the single post widget with a
Columnthat maps over the 2 posts from Firestore (we addedlimit(2)to the query to make sure we only get the latest two). - Query Optimization: Added
.limit(2)to the posts stream to reduce unnecessary data fetching from Firestore.
Optional Performance Tip
Nested StreamBuilders can lead to excessive rebuilds as each stream updates. For better performance, consider combining the streams using rxdart's combineLatest or switching to a single stream that fetches all necessary data at once, but that's a more advanced tweak. For now, the above fixes should get your homepage working correctly!
内容的提问来源于stack exchange,提问作者Saimon Nasy

