I'm not able to read data from Firebase Firestore.
Flutter seems to skip the 'future builder' method.
I'm not getting any error messages, it just seems like Flutter is skipping the code for FutureBuilder() method
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:doctor_app/data/data.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class DatabaseManager {
final user = FirebaseAuth.instance.currentUser;
CollectionReference users =
FirebaseFirestore.instance.collection('users');
// here method GetUserData is called from another file
Future<void> GetUserData() async {
var documentId = user!.email;
print("in getuserdata");
FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
print("in builder");
if (snapshot.hasError) {
print("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {
print("Document does not exist");
}
if (snapshot.connectionState == ConnectionState.done) {
print("in connection");
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
fullname = data['FullName'];
gender = data['Gender'];
dob = data['Dob'];
number = data['Number'];
}
return Text("loading");
},
);
print("at connection end");
}
Related
i trying to get a string/check a string for a validation in my flutter app. i've been trying to use the .where() function but they gave me this error when i did it
The argument type 'Future<QuerySnapshot<Object?>>' can't be assigned to the parameter type 'Future<DocumentSnapshot<Object?>>?'
this is the code that give me the error
final phoneNumber = ModalRoute.of(context)!.settings.arguments as String;
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.where("phoneNumber", isEqualTo : phoneNumber).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return const Text("Something went wrong");
}
if (snapshot == null || !snapshot.data!.exists) {
return const Text("data doesn't exist");
}
if (snapshot.hasData) {
return const Text("data exist already");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text("Full Name: ${data['full_name']} ${data['last_name']}");
}
return const Text("loading");
},
);
been trying and searching for 3-4 hours but all the reference tell me that i need to input the unique id
that will look like this
final docSnapshot = await Firestore.instance
.collection("$Friseur/1/$Tag/1/$Uhrzeit")
.document(${doc_id_here})
.get();
if(docSnapshot.exists) {
setState(...)
}
else {
setState(...)
}
Change FutureBuilder<DocumentSnapshot> to FutureBuilder<QuerySnapshot>
when you use where operation it return the QuerySnapshot.
Add doc function with document id after where function because future parameter accept Future<DocumentSnapshot<Object?>>?
future: users.where("phoneNumber", isEqualTo : phoneNumber).doc(documentId).get(),
I followed some tutos and I add user on firestore successly but I can't print this user on the profile page when the current user is logging because I'm having a error too in my front end.
This is my entire frontend with this error:
The method '[]' can't be unconditionally invoked because the receiver can be 'null'. Try making the call conditional (using '?.') or adding a null check to the target ('!')."
I tried ? and ! but with not success.
hope you help me !
FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc('uid')
.get(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(snapshot.data['displayName'],
);
} else {
return Text("Loading...");
and my backend if needed
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
Future userSetup(String displayName) async {
CollectionReference users = FirebaseFirestore.instance.collection('Users');
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser!.uid.toString();
await users.doc(uid).set({'displayName': displayName, 'uid': uid });
final result = await users.doc(uid).get();
final data = result.data() as Map<String, dynamic>;
return data['displayName'];
}
I followed some tutos and I add user on firestore successly but I can't print this user on the profile page when the current user is logging because doc. is underlined in red in my backend, they say : The getter 'doc' isn't defined for the type 'DocumentSnapshot<Object?>'.
This is my entire backend
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
Future<void> userSetup(String displayName) async {
CollectionReference users = FirebaseFirestore.instance.collection('Users');
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser!.uid.toString();
users.add({'displayName': displayName, 'uid' : uid });
final result = await users.doc(uid).get();
return result.doc.data()['displayName'];
}
Plus I'm having a error too in my front end but I think it's because the backend wrond initialized or just a code wrote.
So this is my front end code:
(userId is red underlined because it's undefined and my [] operators too),
hope you help me !
FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc('uid')
.get(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(snapshot.data['displayName'],
);
} else {
return Text("Loading...");
I edited
FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.get(),
builder: (context, snapshot) {
if (snapshot.hasData)
return Text("Loading...");
if (snapshot.data == null) {
print('Document does not exist on the database');
}else{
return Text("Researching data...");
}
if (snapshot.connectionState == ConnectionState.done) {
var name = snapshot.data as DocumentSnapshot;
return Text(name['displayName'],
);
} else {
return Text("Loading..");
}
},
)
You are not specifying the document ID when creating user, so then, is created unique ID for your user document, and you can't access the document by user ID. And you should also await the creating process. The solution is easy, just specify the document ID when creating user:
Future<void> userSetup(String displayName) async {
CollectionReference users = FirebaseFirestore.instance.collection('Users');
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser!.uid.toString();
await users.doc(uid).set({'displayName': displayName, 'uid': uid });
final result = await users.doc(uid).get();
final data = result.data() as Map<String, dynamic>;
return data['displayName'];
}
Hope it works!
I have difficulties to read (and show) data from firebase DB.
I get this warning:
type '(DocumentSnapshot) => GivitUser' is not a subtype of type '(DocumentSnapshot) => GivitUser'
I realy don't know what I'm doing wrong, I tried to convert from DocumentSnapshot to DocumentSnapshot but without success.
this is my database.dart file:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:givit_app/models/givit_user.dart';
class DatabaseService {
final String uid;
DatabaseService({#required this.uid});
final CollectionReference userCollection =
FirebaseFirestore.instance.collection('Users');
Future<void> updateGivitUserData(
String email, String fullName, String password, int phoneNumber) async {
return await userCollection.doc(uid).set({
'Email': email,
'Full Name': fullName,
'Password': password,
'Phone Number': phoneNumber,
});
}
Future<GivitUser> getGivitUser(String uid) async {
return await userCollection.doc(uid).get().then((user) => user.data());
}
GivitUser _userDataFromSnapshot(DocumentSnapshot<GivitUser> snapshot) {
return GivitUser(
uid: uid,
email: snapshot.data().email,
fullName: snapshot.data().fullName,
phoneNumber: snapshot.data().phoneNumber,
);
}
Stream<GivitUser> get userData {
return userCollection.doc(uid).snapshots().map(_userDataFromSnapshot);
}
}
and this is where I try to use the database.dart file and present the data:
Widget build(BuildContext context) {
GivitUser user = Provider.of<GivitUser>(context);
final DatabaseService db = DatabaseService(uid: user.uid);
return StreamBuilder<GivitUser>(
stream: db.userData,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Loading();
}
print('after getter');
print(snapshot.data);
GivitUser givitUser = snapshot.data;
return Scaffold(
....
....
....
Thank in advance, I will appreciate any help :)
edit: a screenshot of the error:
ERROR SCREENSHOT
I had this exact problem, what helped me was trying to get the collection first and then working on this specific document, maybe try to change this code:
final DatabaseService db = DatabaseService(uid: user.uid);
return StreamBuilder<GivitUser>(
stream: db.userData,
to this code:
final DatabaseService db = DatabaseService(uid: user.uid);
return StreamBuilder<GivitUser>(
stream: db.userCollection.doc(db.uid).get(),
like this documents says https://firebase.flutter.dev/docs/firestore/usage/#one-time-read
and then you can get to the field like:
builder: (context, snapshot) {
/...
Map<String, dynamic> data = snapshot.data.data();
I hope it will help you too! :)
This line userCollection.doc(uid).snapshots() returns Stream<DocumentSnapshot> and not Stream<DocumentSnapshot<GivitUser>> as you declared in the _userDataFromSnapshot argument.
Reference
Stream<DocumentSnapshot> snapshots({bool
includeMetadataChanges = false})
You need to change this block of code below:
GivitUser _userDataFromSnapshot(DocumentSnapshot<GivitUser> snapshot) {
//...
}
to this:
GivitUser _userDataFromSnapshot(DocumentSnapshot snapshot) {
//...
}
snapshot.data() returns a Map<String, dynamic> object.
So you can get your data like you would from a Map object.
The _userDataFromSnapshot method can be updated to:
GivitUser _userDataFromSnapshot(DocumentSnapshot snapshot) {
var snapshotData = snapshot.data() as Map;
return GivitUser(
uid: uid,
email: snapshotData['Email'],
fullName: snapshotData['Full Name'],
phoneNumber: snapshotData['Phone Number'],
);
}
I am getting this exception while running my app:
type 'FirebaseUser' is not a subtype of type 'String'
The app is working. It does the phone authentication and then move to the next page based on same given condition. But when i hit the back button it throws the exception also in the app it is visible.
This is my code.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'AccountDetialsPage.dart';
import 'Homepage.dart';
import 'Phoneverification.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final Firestore firestore = Firestore.instance;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: FutureBuilder(
future: getCurrentUser(),
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Text("Loading...");
}
return StreamBuilder(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData){
return StreamBuilder(
stream: firestore
.collection('users')
.document(snapshot.data)
.snapshots(),
builder: (context, snapshot){
if (snapshot.hasData){
if (snapshot.data["verified"] == true){
return HomePage();
}
else{
return AccountDetialsPage();
}
}
else{
return Text('Loading StreamBuilder');
}
}
);
}
else{
return Phoneverification();
}
},
);
}),
);
}
Future<String> getCurrentUser() async {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseUser user = await _auth.currentUser();
final uid = user.uid;
var number = user.phoneNumber;
return number.toString();
}
}
enter image description here
In your StreamBuilder you set the future to:
stream: FirebaseAuth.instance.onAuthStateChanged,
And then use that in the builder to get data from Firestore with:
stream: firestore
.collection('users')
.document(snapshot.data)
.snapshots(),
The onAuthStateChanged listener is invoked with a FirebaseUser, so snapshot.data in here is a FirebaseUser. Since document(...) expects a string, that's what you get an error about.
Most likely you're looking to use the UID of the user to look up the document, in which case you'd do:
stream: firestore
.collection('users')
.document(snapshot.data.uid)
.snapshots(),
In general your code looks confusing though: in the FutureBuilder you have a future for the current user, and then in your stream builder you also use a listener for that same user.
My feeling is that you're actually trying to use a FutureBuilder for the user, and then a StreamBuilder for the data from Firestore. If that is the case, you're probably looking for something more like:
home: FutureBuilder(
future: getCurrentUser(),
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Text("Loading...");
}
return StreamBuilder(
stream: firestore
.collection('users')
.document(snapshot.data)
.snapshots(),
builder: (BuildContext context, snapshot) {
if (snapshot.hasData){
if (snapshot.data["verified"] == true){
return HomePage();
}
else{
return AccountDetialsPage();
}
}
}
},
);
}),
There might be typos in the above, but the important thing is that the first stream here contains the snapshots from Firestore based on the future: getCurrentUser().