Get user name from a document in Firestore flutter - firebase

I need to display the user name on the profile page. I have tried multiple things but every time it shows an error.
This is what I have done so far:
Widget userProfile(BuildContext context) {
Stream<DocumentSnapshot> provideDocumentUserName() {
return Firestore.instance.collection('user').document('name').snapshots();
}
return Container(
child: StreamBuilder<DocumentSnapshot>(
stream: provideDocumentUserName(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return CircularProgressIndicator();
} else {
Map<String, dynamic> documentFields = snapshot.data.data;
return Text(documentFields["name"]);
}
}));
The error I'm getting is:
The getter 'data' was called on null. Receiver: null Tried calling:
data
Also:
Another exception was thrown: NoSuchMethodError: The method '[]' was called on null.
I have been working on this for hours.

It looks like snapshot.data is null and that's why you might be seeing this error. you might want to check the connection state. one way to tackle is as follows:
switch (snapshot.connectionState) {
case ConnectionState.done:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
Map<String, dynamic> documentFields = snapshot.data;
return Text(documentFields["name"]);
}
return CircularProgressIndicator(); // unreachable
Courtesy to #cipli-onat post here

You should get documentFields as follow:
Map<String, dynamic> documentFields = snapshot.data.data();

Related

Expected a value of type 'Map<String, dynamic>', but got one of type 'Null'

I'm using flutter and managing data by cloud_firestore.
I could send data to firestore, but now I'm Struggling with reading data.
In firestore, data are stored like this;
"users" collection -> "(uid)" document -> "userName" string field
And this is the code which I trying.
Showing LinerProgressIndicator till snapshot has done.
CollectionReference users = FirebaseFirestore.instance.collection('users');
FutureBuilder(
future: users.doc().get(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const SizedBox(
width: 50,
child: LinearProgressIndicator(),
);
}
if (snapshot.hasError) {
return SelectableText(snapshot.error.toString());
}
if (!snapshot.hasData) {
return const Text('No data found');
}
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text("User Name: ${data['userName']}");
},
)
But when snapshot done, error occurred.
Expected a value of type 'Map<String, dynamic>', but got one of type
'Null'
I referenced One-time Read item this official article
I have confirmed that the values ​​for 'users' -> uid -> 'userName' are correct.
Addition 1:
I debugged builder of FutureBuilder.
print('${snapshot.data!.data()}');
null
print('${snapshot.data}');
Instance of '_JsonDocumentSnapshot'
Addition 2:
#Saiful Islam
I rewrote the code.
Then other error occurred.
Expected a value of type 'Map<String, dynamic>', but got one of type '_JsonDocumentSnapshot'
Also, print() result is same as Addition 1.
test code;
CollectionReference users = FirebaseFirestore.instance.collection('users');
FutureBuilder(
future: users.doc(FirebaseAuth.instance.currentUser!.uid).get(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
print('${snapshot.data!.data()}'); //null
print('${snapshot.data}'); //Instance of '_JsonDocumentSnapshot'
if (snapshot.connectionState != ConnectionState.done) {
return const SizedBox(
width: 50,
child: LinearProgressIndicator(),
);
}
if (snapshot.hasError) {
return SelectableText(snapshot.error.toString());
}
if (!snapshot.hasData) {
return const Text('No data found');
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data as Map<String, dynamic>;
return Text("User Name: ${data['username']}");
}
return const SelectableText("userName");
},
)
Addition 3:##
Added print('${jsonDecode(snapshot.data)}').
Error appears again.
Bad state: cannot get a field on a DocumentSnapshotPlatform which does
not exist
Detail of the error;
Launching lib\main.dart on Chrome in debug mode...
This app is linked to the debug service: ws://127.0.0.1:59027/fBobSNPxOzo%3D/ws
Debug service listening on ws://127.0.0.1:59027/fBobSNPxOzo=/ws
Running with sound null safety
Connecting to VM Service at ws://127.0.0.1:59027/fBobSNPxOzo=/ws
════════ Exception caught by widgets library ═══════════════════════════════════
The following StateError was thrown building FutureBuilder<DocumentSnapshot<Object?>>(dirty, state: _FutureBuilderState<DocumentSnapshot<Object?>>#330c8):
Bad state: cannot get a field on a DocumentSnapshotPlatform which does not exist
The relevant error-causing widget was
FutureBuilder<DocumentSnapshot<Object?>> FutureBuilder:file:///D:/FlutterProjects/testProject/lib/profile.dart:32:13
When the exception was thrown, this was the stack
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49 throw_
packages/cloud_firestore_platform_interface/src/platform_interface/platform_interface_document_snapshot.dart 77:7 get
packages/cloud_firestore/src/document_snapshot.dart 92:48 get
packages/cloud_firestore/src/document_snapshot.dart 96:40 _get
packages/testProject/profile.dart 50:45 <fn>
packages/flutter/src/widgets/async.dart 782:48 build
packages/flutter/src/widgets/framework.dart 4782:27 build
packages/flutter/src/widgets/framework.dart 4665:15 performRebuild
packages/flutter/src/widgets/framework.dart 4840:11 performRebuild
packages/flutter/src/widgets/framework.dart 4355:5 rebuild
packages/flutter/src/widgets/framework.dart 2620:31 buildScope
packages/flutter/src/widgets/binding.dart 882:9 drawFrame
packages/flutter/src/rendering/binding.dart 319:5 [_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1143:15 [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1080:9 handleDrawFrame
packages/flutter/src/scheduler/binding.dart 996:5 [_handleDrawFrame]
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/platform_dispatcher.dart 1003:13 invoke
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/platform_dispatcher.dart 157:5 invokeOnDrawFrame
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine.dart 440:45 <fn>
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by rendering library ═════════════════════════════════
A RenderFlex overflowed by 99340 pixels on the bottom.
The relevant error-causing widget was
Column Column:file:///D:/FlutterProjects/testProject/lib/profile.dart:26:20
════════════════════════════════════════════════════════════════════════════════
What kind of problem can you think of?
Thank you.
You should only return Map of the document exists. However, you aren't checking if this condition is true or not.
To be safe, do not return data unless it's inside an if statement, which checks for hasData and then exists.
The error is also probably due to a spelling mistake. Double check that again.
But your error is from the start, with this line:
future: users.doc().get(),
You did not tell which document. You need to pass the id of the document when you run this query.
future: users.doc('0Cb43453fdsg4').get(), //This is an example 'id'.
This should help with your issue
future:
FirebaseFirestore.instance.collection("rates").doc(documentId).get(),
builder: ((context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
(snapshot.data!.data()) as Map<String, dynamic>;
String specifiedData = '${data['specifiedData']}';
return Padding(
padding: const EdgeInsets.all(16.0),
child: Material()}}

Class '_JsonDocumentSnapshot' has no instance method 'call'. Receiver: Instance of '_JsonDocumentSnapshot' Tried calling: call()

I trying to retrieving the data in Firebase with StreamBuilder but it appear this error. Does anyone know how to solve this? Appreciate so much for the help.
This is my code:
Container(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('orderInfo')
.doc(user.uid + 'order')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text('No data');
} else {
Map<String, dynamic> doc =
snapshot.data() as Map<String, dynamic>;
return Text(doc['clLady']);
}
},
))
This is my firebase storage:
I want to retrieve the clID but somehow it does not work.
This is the error message.
Thank you so much!!!
Drop the parenthesis at the end of data like this
Map<String, dynamic> doc =
snapshot.data as Map<String, dynamic>;
snapshot.data is an attribute not a method or callable class, thats why you are getting an error.

Not Showing Placeholder Image even when url in networkimage become's null

GetPhotoUrlStream provide a stream of Url of Profile Photo (data['profilePhoto']) Stored in my Cloud Firebase FireStore. which then being utilized by networkimage to show the profilephoto(circular Avatar)
class GetUserPhotoUrlStream extends StatelessWidget {
final String documentId; // This is your User UID
GetUserPhotoUrlStream(this.documentId);
#override
Widget build(BuildContext context) {
DocumentReference users = FirebaseFirestore.instance.collection('users').doc(documentId);
return StreamBuilder<DocumentSnapshot>(
stream: users.snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Image.asset('assets/images/NouserImage.png');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
Map<String, dynamic> data = snapshot.data.data();
return CircleAvatar(
maxRadius: 80,
backgroundColor: Colors.grey,
child: ClipOval(child: FadeInImage(placeholder: AssetImage('assets/images/NouserImage.png'),image: NetworkImage("${data['profilePhoto']}"),),),
);
},
);
}
}
removeUserPhotoUrl update's the 'profilePhoto' to null which is being used by GetUserPhotoUrlStream.
Future<void> removeUserPhotoUrl(BuildContext context) async
{
var user = _auth.currentUser;
DocumentReference users = FirebaseFirestore.instance.collection('users').doc(user.uid);
users.update({'profilePhoto':null}).then((_){
Navigator.pop(context);
});
await deleteUserImage(context);
notifyListeners();
}
when the value of data['profilePhoto'] is made null using removeUserPhotoUrl it should show me placeholder image which is Provides an assetImage rather it gives an error
Error Message
====================================================================================================
======== Exception caught by image resource service ================================================
Invalid argument(s): No host specified in URI file:///null
====================================================================================================
Also When app is HotReload or HotRestart The Error is Gone and it start Showing Me the PlaceHolder(Asset Image)
Please Help.I want to show Placeholder(Asset Image) as soon as the 'profilePhoto' becomes null
Try this and also make sure that Your images is places inside pubspec.yaml
if (!snapshot.hasData) {
return Image.asset('assets/images/NouserImage.png');
}

Why is print(snapshot.hasData) returning true?

I must be misunderstanding the hasData method for a QuerySnaphot. In my StreamBuilder I want to return a widget informing the user there are no items in the collection queried. I've deleted the collection in Firestore so there's definitely no data there. But when I run the following code:
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('Events')
.where("bandId", isEqualTo: identifier)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
print('code here is being executed 1');// This gets executed
return Text('helllllp');
} else {
print('Code here is being executed2'); //And this gets executed
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Text('Loading...');
default:
return new ListView(
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return CustomCard(
event: document['event'],
location: document['location'],
service: document['service'],
date: document['date'].toDate(),
);
}).toList(),
);
}
}
},
),
All I want to do is return a widget informing user if the snapshot is empty. For example Text('You have no messages')
The problem here is that snapshots() will also return a QuerySnapshot when the query returns no documents. Thus, you could expand your condition like this:
if (!snapshot.hasData || snapshot.data.documents.isEmpty) {
return Text('You have no messages.');
} else {
...
}
Although, realistically you should not return You have no messages when snapshot.data is null because it is null before the query is completed. Hence, I would go for something like this:
if (!snapshot.hasData) {
return Text('Loading...');
}
if (snapshot.data.documents.isEmpty) {
return Text('You have no messages.');
}
return ListView(..);
This ignores error handling, however, that can also be added.
Notice that snapshot.hasData is an alternative to determining connection state using snapshot.connectionState.

Flutter Future:A build function returned null

I want to retrieve data from firebase to future builder.I use this function for that.
Future getAllData() async {
ReseviorDataModel resModel;
DatabaseReference ref = FirebaseDatabase.instance.reference();
DataSnapshot childed =await
ref.child("Reservoir/${widget.placeName}").once();
Map<dynamic, dynamic> values;
values = childed.value;
resModel = ReseviorDataModel.customConstrcutor(values["sensor1"],
values["sensor2"], values["sensor3"]);
return resModel;
}
I invoke this function inside my future builder.
child: FutureBuilder(
future: getAllData(),
builder: (context, snapshot) {
Center(child: Text(snapshot.data));
}
but it keeps throwing this "A build function returned null." error .i cant figure out what is the problem here
To clear things up here, your builder always has to return a widget to display. You can never return null, as the error message describes.
The problem in this case was that the OP didn't return anything from the builder, so just adding a return worked out fine.
Some things to keep in mind when using FutureBuilder. Always check the snapshot.hasData property and return a UI accordingly. This will prevent cases where the snapshot.data is null causing a new error to be thrown in your Widget taking in the null.
Example:
child: FutureBuilder(
future: getAllData(),
builder: (context, snapshot) {
if(!snapshot.hasData) {
// show loading while waiting for real data
return CircularProgressIndicator();
}
return Center(child: Text(snapshot.data));
}

Resources