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

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

Related

Flutter Unhandled Exception: LateInitializationError: Local 'name' has not been initialized

I have a flutter app which tries to compare two sets of app version numbers, the first version number is stored locally using hive and the second version number is from firestore. I can fetch the data from firestore but I cannot get to compare both since it takes a while to fetch data from firestore.
This is the code to fetch data from firestore
late final Box detailsBox;
#override
void initState() {
super.initState();
detailsBox = Hive.box('appDetails');
updateApplication();
}
CollectionReference groceries =
FirebaseFirestore.instance.collection('updates');
late String? name;
late String? version;
late String? downloadUrl;
getData() {
groceries.orderBy('name').snapshots().listen((gets) {
try {
for (var gettt in gets.docs) {
name = gettt['name'] ?? 'null';
version = gettt['version'] ?? 'null';
downloadUrl = gettt['download url'] ?? 'null';
debugPrint('name: $name');
debugPrint('version: $version');
debugPrint('downloadUrl: $downloadUrl');
_addInfo(name!, version!, downloadUrl!); }
} catch (e) {
print(e);
}
});
}
This is the code to compare the version numbers
int getExtendedVersionNumber(String version) {
List versionCells = version.split('.');
if (kDebugMode) {
print(versionCells);
}
versionCells = versionCells.map((i) => int.parse(i)).toList();
return versionCells[0] * 10000 + versionCells[1] * 100 + versionCells[2];
}
Future compareData() async {
await getData();
String localName = detailsBox.get('name');
String localVersion = detailsBox.get('version');
String downloadLink = detailsBox.get('downloadLink');
debugPrint(
'Info retrieved from detailsBox below:\n $localName\n ($localVersion) \n $downloadLink');
debugPrint(
'Info retrieved from firebase below:\n $name\n ($version) \n $downloadUrl');
int version1Number = getExtendedVersionNumber(localVersion); // return 102003
int version2Number = getExtendedVersionNumber(version!); // return 102003
if (kDebugMode) {
print(version1Number == version2Number);
print(version1Number > version2Number);
print(version1Number < version2Number);
}
if (version2Number > version1Number) {
debugPrint('true');
debugPrint(downloadUrl);
}
}
When it gets to this point debugPrint( 'Info retrieved from firebase below:\n $name\n ($version) \n $downloadUrl'); I get the late initialization error [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: LateInitializationError: Field 'name' has not been initialized.
How can I modify the code such that when it runs I can account for the time it takes to get data then finally compare the versions
Just change
late String? name;
to
String? name;

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 To get data from firestore of current user in flutter?

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'];

The argument type 'int' can't be assigned to the parameter type 'Expression<int, IntType>'

I'm using moor_flutter package to interact with sqlite database on flutter app. I'm trying to parse tomorrow as in number of the day in a month. For example the date today is 24, therefore I'm parsing 25 as tomorrow inside the moor_flutter's isSmallerOrEqual() method. The purpose is to parse 25 as in runtimetype **Expression<int, IntType>** but I'm parsing it as runtimetype **int**, This is because I don't know how to convert int to Expression<int, IntType>. I've tried some different approaches but non of them are succeeding.
Below is the function where I'm doing this.
Future NearDueDate() {
// final DateTime currentDate = new DateTime.now();
var dayToday = currentDate.day;
var tommorow = int.parse(dayToday.toString()) + 1;
return (select(the_records)
..where((t_r) => t_r.due_date.day.isSmallerOrEqual(tommorow)))
.get();
}
Note the problem here is how can I convert int to Expression<int, IntType> so that I don't get any error on t_r.due_date.day.isSmallerOrEqual(tommorow)?
Thank you, posted with Love.
Sorry, I can't comment this answer.
If Expression is some kind of model. You would have to convert it by creating an instance of Expression.
Take this for example:
We have a model, User
class User {
int _id;
String _name;
User(this._name);
User.withId(this._id, this._name );
int get id => _id;
String get name => _name;
set name(String newName) {
if (newName.length <= 255) {
this._name = newName;
}
}
// Convert a User object into a Map object
Map<String, dynamic> toMap() {
var map = Map<String, dynamic>();
if (id != null) {
map['id'] = _id;
}
map['name'] = _name;
return map;
}
// Extract a User object from a Map object
User.fromMapObject(Map<String, dynamic> map) {
this._id = map['id'];
this._name = map['name'];
}
}
So this is the main point here
To create a type of User we would do something like this
user = User('John');
Now the type of user.name would be User<String>
Regularly, 'John' would just be a string. Now that it is part of the User class. It is User<String>

When querying the database has the object but getValue() will return null

I keep user per unique value into real time firebase as display at this link image:
get user according to email - database firebase
I want to get user by email, so I try to doing that like this:
private void getUserFromRealtimeFirebase(String email) {
mFirebaseDatabase = FirebaseDatabase.getInstance();
mDatabaseReference = mFirebaseDatabase.getReference().child("user");
Query query = mDatabaseReference.orderByChild("email").equalTo(email);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Log.i("TAG", "dataSnapshot value = " + dataSnapshot.getValue().toString());
if (dataSnapshot.exists()) {
Log.d("Tag", "user exists");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
but I always get at callback listener: dataSnapshot: key = user , value = null even when email exists.
I wonder what is wrong?
EDIT:
If you don't want to pass userId, use this query:
mDatabaseReference = mFirebaseDatabase.getReference();
Query query = mDatabaseReference.orderByChild("user/email").equalTo(email);
You are missing the user-id level.
You should change your code to:
private void getUserFromRealtimeFirebase(String email, String userId) {
mFirebaseDatabase = FirebaseDatabase.getInstance();
mDatabaseReference = mFirebaseDatabase.getReference().chlid(userId).child("user");
Query query = mDatabaseReference.orderByChild("email").equalTo(email);
...
...
}
Btw I would consider re-arranging the data structure to -
newsapp -> users -> {userId} -> {name, image, firebase-token, email....}.
Also, on the callback - first check if dataSnapshot.exists() and only after that use getValue(), even if inside a log, to avoid null pointer exception.

Resources