How To get data from firestore of current user in flutter? - firebase

I want to get data of authenticated user from firestore and put them in variables in flutter, I do not need to display them on the screen I just want to store them in variables : I created file data.dart It has only variables . this is the file contains the variables(data.dart) (I dont have statefull widget or stateless widget) :
and this is the file where I called The variables(firbaseapi.dart):
String myId = "AfhUxYFIaHTvSOyOPlh14essssq9pJpW2"; // I want to get user id here
String myUsername = 'Sabri'; // I want to get username here
String myUrlAvatar = 'http//kdkskdskd'; // I want to get avatar URL here
I tried this but I got an error :
A value of type 'Future' can't be assigned to a variable of type 'DocumentSnapshot'.
Try changing the type of the variable, or casting the right-hand type to 'DocumentSnapshot'
User user = FirebaseAuth.instance.currentUser;
DocumentSnapshot snap =
FirebaseFirestore.instance.collection('Users').doc(user.uid).get();//error appear here
String myId = snap['uid'];
String myUsername = snap['name'];
String myUrlAvatar = snap['avatarurl'];

working example!
imports
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
Global
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
String myId = '';
String myUsername = '';
String myUrlAvatar = '';
Method to get data from firestore.
void _getdata() async {
User user = _firebaseAuth.currentUser;
FirebaseFirestore.instance
.collection('users')
.doc(user.uid)
.snapshots()
.listen((userData) {
setState(() {
myId = userData.data()['uid'];
myUsername = userData.data()['name'];
myUrlAvatar = userData.data()['avatarurl'];
});
}
Get data when screen starts in a stateful widget you can also call method on button press.
#override
void initState() {
super.initState();
_getdata();
}

DocumentSnapshot snap = FirebaseFirestore.instance.collection('your collection').get();
String myId = snap['myId'];
String myUsername = snap['myUsername'];
String myUrlAvatar = snap['myUrlAvatar'];
Update:
User user = FirebaseAuth.instance.currentUser;
DocumentSnapshot snap = FirebaseFirestore.instance.collection('Users').doc(user.uid).get();
String myId = snap['uid'];
String myUsername = snap['name'];
String myUrlAvatar = snap['avatarurl'];

Related

The method '[]' can't be unconditionally invoked because the receiver can be 'null' | Firebase Database | Flutter

I'am getting the 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 ('!'). Below is my code
import 'package:firebase_database/firebase_database.dart';
class Users {
String? id;
String? email;
String? name;
String? phone;
Users({
this.id,
this.email,
this.name,
this.phone,
});
Users.fromSnapshot(DataSnapshot dataSnapshot) {
id = dataSnapshot.key!;
email = dataSnapshot.value['email'];
name = dataSnapshot.value['name'];
phone = dataSnapshot.value['phone'];
}
}
The Error is in the last 3 lines
email = dataSnapshot.value['email'];
name = dataSnapshot.value['name'];
phone = dataSnapshot.value['phone'];
I have already added null safety operators. But it still shows an error.
A DataSnapshot object does not necessarily have a value, so its value property may be null. You need to check whether the snapshot has a value, before trying to read properties from it:
Users.fromSnapshot(DataSnapshot dataSnapshot) {
id = dataSnapshot.key!;
if (dataSnapshot.value != null) {
email = dataSnapshot.value!['email'];
name = dataSnapshot.value!['name'];
phone = dataSnapshot.value!['phone'];
}
}
Note the added if statements, and the ! marks that Pokaboom also commented about.
Users.fromSnapshot(DataSnapshot dataSnapshot) {
List<User> userData = dataSnapshot.value!.toList();
id = dataSnapshot.key!;
email = userData['email'];
name = userData['name'];
phone = userData['phone'];
}
maybe this work

The argumnet type 'Null Funcion(DataSnapshot)' cnt be assigned to the parameter type 'Future Or <dynamic> Function(DataBaseEvent)'

I have this function that is giving me an error.
the getCurrentOnLineUserInfo function is trying to get read data from the Firebase Database of the current user that is logged in.
The argument type 'Null Funcion(DataSnapshot)' can't be assigned to the parameter of type 'Future Or Function(DataBaseEvent)'
I am following a year-old tutorial, so the issue might be the code is old. I might need new syntax or something.
static void getCurrentOnLineUserInfo() async {
firebaseUser = await FirebaseAuth.instance.currentUser;
String userId = firebaseUser!.uid;
DatabaseReference reference =
FirebaseDatabase.instance.ref().child("user").child(userId);
print("getCurrentOnLineUser info executed!");
print('${firebaseUser!.email}${firebaseUser!.displayName}');
// errors below this
reference.once().then((DataSnapshot dataSnapshot) {
if (dataSnapShot!.value != null) {
userCurrentInfo = Users.fromSnapshot(dataSnapshot);
}
});
}
}
and here is my class that is assigning data. This class is giving no errors
class Users {
String? id;
String? email;
String? phone;
String? name;
Users({this.id, this.email, this.phone, this.name});
Users.fromSnapshot(DataSnapshot dataSnapshot) {
id = dataSnapshot.key!;
var data = dataSnapshot.value as Map?;
if (data != null) {
email = data?["email"];
name = data?["name"];
phone = data?["phone"];
}
}
}
The once method returns a DatabaseEvent, not a DataSnapshot. DatabaseEvent is a class that encapsulates a DataSnapshot AND a DatabaseEventType, to extract the snapshot, you must use DatabaseEvent.snapshot:
reference.once().then((event) {
final dataSnapshot = event.snapshot;
if (dataSnapShot!.value != null) {
userCurrentInfo = Users.fromSnapshot(dataSnapshot);
}
});
Here is another solution I think might do what you want:
// async methods should return a future
static Future<void> getCurrentOnLineUserInfo() async {
firebaseUser = await FirebaseAuth.instance.currentUser;
String userId = firebaseUser!.uid;
DatabaseReference reference =
FirebaseDatabase.instance.ref().child("user").child(userId);
final snapshot = await reference.get(); // you should use await on async methods
if (snapshot!.value != null) {
userCurrentInfo = Users.fromSnapshot(snapshot);
}
}
}
I was following the same old tutorial you mentioned, the #mobdev991 answer is correct and i think the reason why you don't receive data is the class where you are assigning data try this
class Users {
String? id;
String? email;
String? name;
String? phone;
Users({this.id, this.email, this.name, this.phone});
Users.fromSnapshot(DataSnapshot dataSnapshot) {
id = dataSnapshot.key;
email = (dataSnapshot.child("email").value.toString());
name = (dataSnapshot.child("name").value.toString());
phone = (dataSnapshot.child("phone").value.toString());
}
}

How do I write tests for a transformed stream in Flutter?

I have a Provider which has a method which takes data from Firebase as a stream, transforms it to a list and returns a Stream<List<Model>> . I'm trying to write a test where I want to check if the items in the List are the same as I expect them to be. How can I do that?
My Current Code:
test('getContacts returns a empty list when there is no contact',() async{
when(sharedPreferencesMock.get(any)).thenReturn('uid'); //mock the sharedprefs
documentSnapshot = DocumentSnapshotMock(); //mock documentsnapshot
when(documentSnapshot.exists).thenReturn(true); // this is done to pass the getUidByUsername method
documentReference = DocumentReferenceMock(documentSnapshotMock: documentSnapshot);
documentReference.setData({
'uid':'uid',
'contacts':[] // setting the usename in the data already so that duplicate contact exception is thrown
});
userDataProvider.getContacts().asBroadcastStream().listen((data){
expect(data.length,0);
});
});
And the provider method
#override
Stream<List<Contact>> getContacts() {
CollectionReference userRef = fireStoreDb.collection(Paths.usersPath);
DocumentReference ref =
userRef.document(SharedObjects.prefs.get(Constants.sessionUid));
return ref.snapshots().transform(StreamTransformer<DocumentSnapshot, List<Contact>>.fromHandlers(handleData: (documentSnapshot, sink) async{
List<String> contacts;
if (documentSnapshot.data['contacts'] == null) {
ref.updateData({'contacts': []});
contacts = List();
} else {
contacts = List.from(documentSnapshot.data['contacts']);
}
List<Contact> contactList = List();
for (String username in contacts) {
print(username);
String uid = await getUidByUsername(username);
DocumentSnapshot contactSnapshot = await userRef.document(uid).get();
contactList.add(Contact.fromFirestore(contactSnapshot));
}
sink.add(contactList);
}));
}
Update:
StreamController streamController = StreamController<List<Contact>>();
StreamSink<List<Contact>> sink = streamController.sink;
Stream<List<Contact>> stream = streamController.stream;
stream.listen((List<Contact> list){
expect(list.length,1);
});
userDataProvider.mapDocumentToContact(userCollection, userRef, documentSnapshot, sink);
streamController.close();
Make the lambda function that you currently pass to the StreamTansformer a separate function and test that.
If you want to test the full function there is a Firebase mock package on pub.

How do I get my document fields into a model field from Firestore

I have a list of documents from Firestore (postItemz). I wish to pass these into a model (Post) built to hold the data
class PostViewModel {
List<Post> postItems;
PostViewModel({this.postItems});
DocumentReference postItemz = Firestore.instance.collection('posts').document('post-items');
}
class Post {
String personName;
int commentsCount;
List<String> photos;
Post(
{this.personName,
this.commentsCount,
this.photos});
}
I want to pass the fields returned from the 'postItemz' firestore collection into the List object?
Hope you are trying to parse a single firestore document
define your post class as below
class Post {
String documentID;
String personName;
int commentsCount;
List<String> photos;
Post.fromSnapshot(DocumentSnapshot snapshot)
: documentID = snapshot.documentID,
personName = snapshot['personName'],
commentsCount = snapshot['commentsCount'],
photos = snapshot['photos'].cast<String>()
;
}
get the document snapshot and parse
var postItemz = await Firestore.instance.collection('posts').document('post-items').get();
var data = Post.fromSnapshot(postItemz );
to parse multiple documents
get the document snapshots using the method getDocuments() and parse
var newData = snapShotdata.documents.map((snapshot) {
return Post.fromSnapshot(snapshot);
}).toList();
Hope it helps!

In Flutter save firebase real time data in local storage json and populate list view from json

In flutter, I want to get data from firebase realtime database and save it in local storage as json and populate list view from that json. If database updated in firebase ,then Json should get update and should reflect in list view.
DataSnapshot firebaseData;
File allnews_json;
Directory dir;
String allnews_filename = "allnews.json";
bool fileExists = false;
#override
void initState() {
super.initState();
getApplicationDocumentsDirectory().then((Directory directory) {
dir = directory;
allnews_json = new File(dir.path + "/" + allnews_filename);
fileExists = allnews_json.existsSync();
if (fileExists) this.setState(() => fileContent = JSON.decode(allnews_json.readAsStringSync()));
});
FirebaseDatabase.instance.reference().child('news')
.once()
.then((onValue) {
firebaseData = onValue.value;
write(firebaseData);
});
}
void write(DataSnapshot snapshot) async {
print("Creating file!");
File file = new File(dir.path + "/" + allnews_filename);
file.createSync();
final String key = snapshot.key;
final String headline = snapshot.value['title'];
final int news = snapshot.value['content'];
String content = '{"$key":{"headline":"$headline","news":"$news"}}';
file.writeAsStringSync(content);
}
This is the code i have so far. But there is something wrong in this too.

Resources