Reputation: 1037
I have seen similar questions and answers being solved with the StreamBuilder widget.
In my case when I am implementing it my code does not await to fetch the data and just moves on (in my case, the app jumps to the next page). Thus, do I need the build a StreamBuilder Widget or is there a simple method that could work and fetch the data in realtime?
I noticed that I did not use async* with the asterisc but if I do so, then the authentication is not working.
Clarification:
The code does not enter the following lines:
if (!snapshot.hasData)
return new Text('Loading...');
return new Text(
snapshot.data.data['name']
);
Also the print(test);
statement prints the following:
StreamBuilder<DocumentSnapshot>
Here is the whole part:
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
LoginScreen.user =
await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (LoginScreen.user != null) {
// get the users data and save them
if (LoginScreen.user.user.uid !=
'IDVwQXAsZas213Va0OIH2IsoU5asdaTfraBJ2') {
Widget test = await StreamBuilder<DocumentSnapshot>(
stream: _firestore
.collection('Employees')
.document(LoginScreen.user.user.uid)
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData)
return new Text('Loading...');
return new Text(
snapshot.data.data['name']
);
},
);
print(test);
Navigator.pushReplacementNamed(
context, TabCreator.screenId);
} else {
}
}
} catch (e) {
print(e);
// when getting an erro stop spinner
setState(() {
showSpinner = false;
});
}
}
Update:
I created a new standard flutter project in order to see if there was something else within my code that was messing the StreamBuilder. I am still getting no output.
On a side note when I am implementing the following code within the onPressed method I am getting the wanted result:
Alternative Solution:
onPressed: () {
DocumentReference documentReference = await Firestore.instance
.collection('Employees')
.document('8nss0gppzNfOBMuRz9H44dv7gSd2');
documentReference.snapshots().listen((datasnapshot) {
if (datasnapshot.exists) {
print(datasnapshot.data['name'].toString());
} else {
print('Error!');
}
});
}
Here is the implemented StreamBuilder implemented in the standard Flutter project:
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _auth = FirebaseAuth.instance;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'Testing',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// DocumentReference documentReference = await Firestore.instance
// .collection('Employees')
// .document('8nss0gppzNfOBMuRz9H44dv7gSd2');
// documentReference.snapshots().listen((datasnapshot) {
// if (datasnapshot.exists) {
// print(datasnapshot.data['name'].toString());
// } else {
// print('Error!');
// }
// });
StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('Employees')
.document('8nss0gppzNfOBMuRz9H44dv7gSd2')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Text('Loading...');
default:
return new Text(snapshot.data.data['name']);
}
},
);
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Upvotes: 0
Views: 63
Reputation: 80914
Change your code to the following:
builder: : (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData){
return new Text('Loading...');
}
else{
print(snapshot);
Navigator.pushReplacementNamed(
context, TabCreator.screenId);
}
Add an else
block so when you have data it will enter the else
and navigate to the page.
Also you need to use the StreamBuilder
inside the build
method not inside the onPressed
function which is used to handle data processing. Example you can do the following:
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
bool visible = false;
final firestoreInstance = Firestore.instance;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
Visibility(
child: StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('users')
.document('FIJbBBiplAGorYzdtUQF')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
print(snapshot);
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else if (snapshot.hasData) {
print(snapshot.data.data);
return new Text(snapshot.data.data["age"].toString());
}
return new CircularProgressIndicator();
},
),
visible: visible,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
visible = true;
});
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
So here I also use the Visibility()
widget to hide it, but when FAB button is clicked the data from firestore will appear.
Upvotes: 1