I am trying get User Name through a document stored in users collection in cloud firestore but my build method runs before the data is received.
The initState(){} method does not wait for uidDetails() to complete and therefore null values are passed in DoctorListStream(currentUserName) . Since the initState(){}` method cannot be made async I want to know what can be done to fix this. I have also tried to implement both StreamBuilder and FutureBuilder but failed.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import '../components/doc_list_retriever.dart';
class ListOfDoctors extends StatefulWidget {
#override
_ListOfDoctorsState createState() => _ListOfDoctorsState();
}
class _ListOfDoctorsState extends State<ListOfDoctors> {
final _auth = FirebaseAuth.instance;
final _fStore = Firestore.instance;
String currentUserUid;
String currentUserName;
#override
void initState() {
// TODO: implement initState
super.initState();
uidDetails();
}
void uidDetails() async {
final FirebaseUser user = await _auth.currentUser();
currentUserUid = user.uid;
print(currentUserUid + 'from user details');
await Firestore.instance
.collection('users')
.document(currentUserUid)
.get()
.then((DocumentSnapshot) {
currentUserName = DocumentSnapshot.data['name'].toString();
});
print(currentUserName + ' from uid Details');
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF1D1E33),
body: SafeArea(
child: Column(
children: <Widget>[
Text(
'Doctors:',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 40, color: Colors.white70),
),
DoctorListStream(currentUserName),
],
),
),
);
}
}
CONSOLE :
Performing hot restart...
Syncing files to device AOSP on IA Emulator...
Restarted application in 848ms.
I/BiChannelGoogleApi(27263): [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzaq#95a83d7
D/FirebaseAuth(27263): Notifying id token listeners about user ( 5TlH5zoCqfWDNDlAgvIsc5yAHPA3 ).
I/flutter (27263): 5TlH5zoCqfWDNDlAgvIsc5yAHPA3from user details
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building StreamBuilder<QuerySnapshot>(dirty, state: _StreamBuilderBaseState<QuerySnapshot, AsyncSnapshot<QuerySnapshot>>#044e7):
The method '+' was called on null.
Receiver: null
Tried calling: +(" from doctor list stream")
The relevant error-causing widget was:
StreamBuilder<QuerySnapshot> file:///D:/projects/clinic/lib/components/doc_list_retriever.dart:14:12
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 DoctorListStream.build.<anonymous closure> (package:clinic/components/doc_list_retriever.dart:26:27)
#2 StreamBuilder.build (package:flutter/src/widgets/async.dart:509:81)
#3 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:127:48)
#4 StatefulElement.build (package:flutter/src/widgets/framework.dart:4623:28)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (27263): Dhruv from uid Details
════════ Exception caught by rendering library ═════════════════════════════════════════════════════
A RenderFlex overflowed by 99670 pixels on the bottom.
The relevant error-causing widget was:
Column file:///D:/projects/clinic/lib/screens/list_of_doctors.dart:43:16
════════════════════════════════════════════════════════════════════════════════════════════════════
I would opt to using a stream builder to get the user data. sample implementation
String username;
body: StreamBuilder(
stream: Firestore.instance
.collection('users')
.document(userid)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SpinKitDoubleBounce(
color: Colors.blue,
);
}
var userDoc = snapshot.data;
userName = userDoc["name"];
return .... //your other widgets
Related
This question already has answers here:
No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() in Flutter and Firebase
(27 answers)
Closed 1 year ago.
Error : no firebase app has been created call firebase.initializeapp
My Question : Where should i need to add firebase initialization
A stateless widget with firestore reference 'users'
class FeedBack extends StatelessWidget {
CollectionReference users = FirebaseFirestore.instance.collection('users');
late String txtnote;
late String note;
#override
Widget build(BuildContext context) {
return Scaffold(
onpress integration for writing data to firestore
child: ElevatedButton(
onPressed: () async {
await users.add({
'subject': note,
'email': 'example#gmail.com',
'description': txtnote
}).then((value) => print('Data Added Successfully!'));
},
child: Text(
'Submit',
style: TextStyle(color: Colors.white),
),
Note : This dart file 'feedback.dart' does not contain void main function its a stateless widget
You can call inside the main entry point of your app:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
As a default, this should go in the main.dart file
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
this error "
"The getter 'uid' was called on null.Receiver: nullTried calling: uid"
I Faced when i try to sign out from any screen "except home screen" ,
is there any solution for this problem ??
Wrapper :
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User_fb>(context);
// return home or login
if (user == null) {
return Login();
} else {
print(user.uid);
return Home();
}
}
}
auth :
Future Signinwithemailandpassword(var Res_email,var Res_Password) async{
try{
UserCredential result= await _auth.signInWithEmailAndPassword(email: Res_email, password: Res_Password);
User user = result.user;
return _userfromfirebase(user);
}catch(e){
return null;
}
}
Future signOut () async{
try{
return await _auth.signOut();
}
catch(e){
print(e.toString());
print("error at signOut ");
return null;
}
}
main :
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(Main());
}
class Main extends StatefulWidget {
#override
_MainState createState() => _MainState();
}
class _MainState extends State<Main> {
#override
Widget build(BuildContext context) {
return StreamProvider<User_fb>.value(
value: Authservice().user,
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color.fromRGBO(255, 255, 255, 1),
shadowColor: Colors.transparent,
highlightColor: Colors.transparent),
home: Wrapper(),
),
);
}
}
Sign-out button :
ListTile(
leading: Icon(Ionicons.log_out_outline,
color: Color.fromRGBO(86, 197, 150, 1)),
title: Text('Log out'),
onTap: () async {
await _auth.signOut();
},
),
console :
======== Exception caught by widgets library =======================================================
The following NoSuchMethodError was thrown building Br(dirty, dependencies: [_InheritedProviderScope<User_fb>], state: _QrState#24e19):
The getter 'uid' was called on null.
Receiver: null
Tried calling: uid
The relevant error-causing widget was:
Qr file:///G:/AndroidStudioProjects/facem/lib/Screens/Home/Home.dart:687:67
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 _QrState.build (package:my_compound/Screens/Qr/qr.dart:99:45)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4691:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4574:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4746:11)
...
this happens because user is null, So use null check operator.
something like this user?.uid or user.uid ?? '',
TIP: Alway use dart null safety when using flutter.
I recently got started with firebase firestore and this is one error I cant seem to find a answer to, I tried writing snapshot.data.documents as docs, doc and document after looking at answers for similar questions but it is still throwing the same error. what do I do?
firestore version I am using is cloud_firestore: ^1.0.7
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
// import 'package:vola1/colors.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
class test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
// floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('countries')
.doc('nW9L4LGpn2MZVyiTyUII')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Text('Loading data.. please wait..');
return Column(
children: <Widget>[
Text(
snapshot.data.doc[0]['name'],
style: TextStyle(fontSize: 20),
),
],
);
},
));
}
}
the exception it is throwing
======== Exception caught by widgets library =======================================================
The following NoSuchMethodError was thrown building StreamBuilder<DocumentSnapshot>(dirty, state: _StreamBuilderBaseState<DocumentSnapshot, AsyncSnapshot<DocumentSnapshot>>#af0fe):
Class 'DocumentSnapshot' has no instance getter 'documents'.
Receiver: Instance of 'DocumentSnapshot'
Tried calling: documents
The relevant error-causing widget was:
StreamBuilder<DocumentSnapshot> file:///D:/flutter%20course/vola1/lib/test.dart:14:15
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 test.build.<anonymous closure> (package:vola1/test.dart:24:29)
#2 StreamBuilder.build (package:flutter/src/widgets/async.dart:545:81)
#3 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:124:48)
#4 StatefulElement.build (package:flutter/src/widgets/framework.dart:4612:27)
...
====================================================================================================
To get the data from a DocumentSnapshot, use the data getter which retrieves all fields in the document as a Map;
docs is for the QuerySnapshot class.
Change this code below:
snapshot.data.doc[0]['name'],
to this:
snapshot.data['name'],
I have an issue with firebase and flutter. I'm building app with signing in and displaying list of expenses from collection, which name is user id. When the user signs in, he will see list with items from his collection. I used Stream method. The problem is that before user signs in, stream recieves null id and the app crashes. Is there any way to set this stream after user signs in? I will be thankful for any help!
This is the error
The following assertion was thrown building Home(dirty):
'package:cloud_firestore/src/firestore.dart': Failed assertion: line 72 pos 12: 'path != null': is not true.
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
The relevant error-causing widget was
Home
lib\screens\wrapper.dart:18
When the exception was thrown, this was the stack
#2 Firestore.collection
package:cloud_firestore/src/firestore.dart:72
#3 DatabaseService.expenses
package:expenses_app/services/database.dart:38
#4 Home.build
package:expenses_app/…/home/home.dart:27
#5 StatelessElement.build
package:flutter/…/widgets/framework.dart:4291
#6 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4223
this is stream in database file
Stream<QuerySnapshot> get expenses {
return firestoreReference.collection(uid).snapshots();
}
this is widget, which loads after user signs in
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:expenses_app/services/auth.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:expenses_app/services/database.dart';
import 'package:provider/provider.dart';
import 'expenses_list.dart';
class Home extends StatelessWidget {
static String currentUid;
final AuthService _auth = AuthService();
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
void getUid() async {
final FirebaseUser user = await firebaseAuth.currentUser();
currentUid = user.uid;
//print(currentUid);
}
#override
Widget build(BuildContext context) {
getUid();
return StreamProvider<QuerySnapshot>.value(
value: DatabaseService(uid: currentUid).expenses,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.red[400],
title: Text('Expenses App'),
elevation: 0.0,
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.person,
color: Colors.white,),
onPressed: () async {
await _auth.signOut();
},
label: Text('Logout',
style: TextStyle(color: Colors.white),),
)
],
),
body: ExpensesList(),
),
);
}
}
This is the error
you are building widgets before id arrive check if the id is not null before build return, if the id is null return empty container e
I found some issue thread with people also not being able to complete transactions, but it does not even provide solutions.
Problem
Suddenly, my transactions crashes when using transaction.get.
runTransaction(
(Transaction transaction) async {
await transaction.get(documentReference); // "Timed out waiting for Task"
}
The PlatformException does also not really help me because it crashes in platform_channel...
E/flutter (16297): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (16297): PlatformException(Error performing transaction, Timed out waiting for Task, null)
E/flutter (16297): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:547:7)
E/flutter (16297): #1 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:279:18)
E/flutter (16297): <asynchronous suspension>
E/flutter (16297): #2 Firestore.runTransaction (file:///G:/flutter/.pub-cache/hosted/pub.dartlang.org/cloud_firestore-0.7.3/lib/src/firestore.dart:115:10)
// here comes another <asynchronous suspension> followed by my code
This comes from Android.
This Error comes sometimes because:
don't debug the transaction while it's running, so put the breakpoint in a proper line before or after.
Another errors come because you don't :
do all get calls first, then your write or update comes.
as Firestore document said:
"Read operations must come before write operations."
https://firebase.google.com/docs/firestore/manage-data/transactions#transactions
The issue I was having has since been fixed by the cloud_firestore team.
If you are still experiencing a similar issue, you should either ask a question here on StackOverflow or create an issue.
Note: You can also make atomic changes to data using transactions.
While this is a bit heavy-handed for incrementing a vote total, it is
the right approach for more complex changes. Here is what a
transaction that updated the votes count might look like.
onTap: () => Firestore.instance.runTransaction((transaction) async {
final freshSnapshot = await transaction.get(record.reference);
final fresh = Record.fromSnapshot(freshSnapshot);
await transaction
.update(record.reference, {'votes': fresh.votes + 1});
}),
How does this work? By wrapping the read and write operations in one
transaction, you're telling Cloud Firestore to only commit a change if
there was no external change to the underlying data while the
transaction was running. If two users aren't concurrently voting on
that particular name, the transaction runs exactly once. But if the
number of votes changes between the transaction.get(...) and the
transaction.update(...) calls, the current run isn't committed, and
the transaction is retried. After 5 failed retries, the transaction
fails.
Source
https://codelabs.developers.google.com/codelabs/flutter-firebase/index.html#10
This works without any problems:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
Future<void> main() async {
final FirebaseApp app = await FirebaseApp.configure(
name: 'yourappname',
options: const FirebaseOptions(
googleAppID: 'yourgoogleid',
gcmSenderID: 'yourgmssenderid',
apiKey: 'yourapikey',
projectID: 'yourprojectid',
),
);
final Firestore firestore = Firestore(app: app);
await firestore.settings(
timestampsInSnapshotsEnabled: true,
persistenceEnabled: true,
sslEnabled: true
);
runApp(MaterialApp(
title: 'Firestore Example', home: MyHomePage(firestore: firestore)));
}
class MessageList extends StatelessWidget {
MessageList({this.firestore});
final Firestore firestore;
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('messages').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
final int messageCount = snapshot.data.documents.length;
return ListView.builder(
itemCount: messageCount,
itemBuilder: (_, int index) {
final DocumentSnapshot document = snapshot.data.documents[index];
return ListTile(
title: Text(document['message'] ?? '<No message retrieved>'),
subtitle: Text('Message ${index + 1} of $messageCount'),
);
},
);
},
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({this.firestore});
final Firestore firestore;
CollectionReference get messages => firestore.collection('messages');
Future<void> _addMessage() async {
final DocumentReference postRef = firestore.document('posts/123');
firestore.runTransaction((Transaction tx) async {
DocumentSnapshot postSnapshot = await tx.get(postRef);
if (postSnapshot.exists) {
await tx.update(postRef, <String, dynamic>{'likesCount': postSnapshot.data['likesCount'] + 1});
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firestore Example'),
),
body: MessageList(firestore: firestore),
floatingActionButton: FloatingActionButton(
onPressed: _addMessage,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}