Flutter新手求助:StreamBuilder中snapshot.data始终为null
Hey there! Let's walk through why your StreamBuilder isn't pulling in data from Firestore. I've worked through similar headaches when starting out with Flutter and Firestore, so here are the most likely fixes to try:
1. Check if the Firestore Document Actually Exists
The biggest culprit here is probably that the document matching user.uid doesn't exist in your brews collection yet.
Firestore's snapshots() stream behaves a bit uniquely when the target document is missing:
- It won't throw an error, but will return a snapshot where
hasDataisfalseanddataisnull - The
connectionStatestays inactive(notdone) because the stream is still listening for changes (like if the document gets created later)
Fix:
- Head to your Firebase Console → Firestore Database → Check the
brewscollection for a document with the ID matching your user'suid. - If it's missing, either create a test document manually in the console, or add code to auto-create it when a user signs up (using the
updateUserDatamethod I'll mention later).
2. Verify Firestore Security Rules
Even if you're authenticated, strict security rules might be blocking access to the document.
Make sure your rules allow the logged-in user to read their own document. Here's a standard rule set for this use case:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /brews/{docId} { allow read, write: if request.auth != null && request.auth.uid == docId; } } }
Double-check that your rules don't have typos or overly restrictive conditions.
3. Fix Type Mismatch in UserData Class
Looking at your UserData class, I spotted a potential type mismatch that could cause issues down the line:
- Your class defines
strengthas aString, but in Firestore you're storing it as an integer (from the slider's rounded value). - This won't directly make
hasDatafalse, but it will lead to runtime errors when you try to use the data.
Fix:
Update the UserData class to match the Firestore data types:
class UserData { final String uid; final String name; final int strength; // Changed from String to int final int sugars; UserData({ this.uid, this.sugars, this.strength, this.name }); }
4. Improve StreamBuilder State Handling
Right now your code only checks hasData, but StreamBuilder has multiple connection states you should handle to make debugging easier and improve user experience.
Updated Builder Code:
builder: (context, snapshot) { // Show loading while connecting to Firestore if (snapshot.connectionState == ConnectionState.waiting) { return Loading(); } // Handle any errors that occur if (snapshot.hasError) { return Center(child: Text('Oops! Something went wrong: ${snapshot.error}')); } // Handle the case where the document doesn't exist if (!snapshot.hasData || snapshot.data == null) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("Looks like you don't have any brew settings yet!"), SizedBox(height: 16), RaisedButton( color: Colors.pink[400], child: Text('Set Up Your Preferences', style: TextStyle(color: Colors.white)), onPressed: () async { // Create initial document with default values await DatabaseService(uid: user.uid).updateUserData('Your Name', '0', 100); }, ), ], ), ); } // If we get here, we have valid data to use UserData userData = snapshot.data; return Form( key: _formKey, child: Column( // Your existing form code here... ), ); }
Don't forget to add the updateUserData method to your DatabaseService class to save data to Firestore:
Future updateUserData(String name, String sugars, int strength) async { return await brewCollection.document(uid).setData({ 'name': name, 'sugars': sugars, 'strength': strength, }); }
Start with checking if the document exists in Firestore—that's the most common issue here. Once you fix that, your StreamBuilder should start pulling in data as expected!
内容的提问来源于stack exchange,提问作者Akash Punagin




