I have a problem with Firebase in Flutter
This is the code:
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection("tasks").snapshots(),
builder:(context, AsyncSnapshot<QuerySnapshot>snapshot){
if(!snapshot.hasData) return LinearProgressIndicator();
return Expanded(
child: _buildList(snapshot.data)
);
}
)
And the console tell me:
Error: The argument type 'QuerySnapshot<Object?>?' can't be assigned
to the parameter type 'QuerySnapshot<Object?>' because
'QuerySnapshot<Object?>?' is nullable and 'QuerySnapshot<Object?>'
isn't. lib/main.dart:82
'QuerySnapshot' is from 'package:cloud_firestore/cloud_firestore.dart'
('/C:/src/flutter/.pub-cache/hosted/pub.dartlang.org/cloud_firestore-3.1.4/lib/cloud_firestore.dart').
package:cloud_firestore/cloud_firestore.dart:1
'Object' is from 'dart:core'.
child: _buildList(snapshot.data)
I can't understand the problem.
Thanks
snapshot.data could be null, that means it is nullable. You already made sure it won't be null by adding an if (snapshot.hasData), but dart doesn't know that. So in order to let dart know that you've made sure a nullable value is not null, you should add a null check operator (!):
_buildList(snapshot.data!);
This means you will get an error if snapshot.data is null, but in this case it won't be because you already checked before.
Related
I have a problem here with flutter (v2.8.1) on my windows.
I am trying to use StreamBuilder class to fetch data from firebase but it is not working anyhow. I tried to use BuildContext context but it is still throwing me error on context.
Please have a look at my code and let me know what I am doing wrong. Answers are appreciated. Thanks in advance.
StreamBuilder(builder: (BuildContext context, snapshot), stream: _firestore.collection('messages').snapshots()),
Error :
The argument type 'Type' can't be assigned to the parameter type 'Widget Function(BuildContext, AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>>)'.
Please check the image : https://imgur.com/a/QJs6hS9
The builder argument should be a function that returns a widget.
builder: (context, snapshot) {
// return a widget that uses the snapshot
// for example
return Text(snapshot.data().title);
}
I got the same problem with null statements (?) in Dart multiple times in different cases. I really hope somebody can help me.
Just added some lines of code & the error:
Error:
The property 'isEmpty' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!'). here
Here is one of my examples:
child: MaterialButton(
onPressed: () {
var currentState = this._formKey.currentState;
if (currentState == null) {
return;
}
if (_formKey.currentState.validate()) {
AuthService.instance.signIn(
email: emailTextEditingController.text,
password:
passwordTextEditingController.text);
if (AuthService.instance
.checkIfUserExists() ==
true) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => MainMenu()));
} else {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
VerifyScreen()));
}
}
},
Got this error-message again:
The method 'validate' 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 ('!').
After I edited the code with a ! to avoid the Null-Statement like:
singUpUser() {
if (formKey.currentState!.validate()) {
setState(() {
isLoading = true;
});
} else {
return null;
};
But now i just avoid the error in the code itself, after starting a emulator and testing it, next error appears:
Null check operator used on a null value
So thats not the right solution...
If you need more code, just message me.
Thank you!
Tom
In a nutshell: if Dart is certain that a variable at compile time can be null at runtime, it doesn't compile.. unless you explicitly check for null values, and/or promote the variable to be non-nullable with the ! operator (Dart is not always able to infer the non-nullability in certain situations, so it's our responsibility to promote them to non-nullable).
There's much more to know if you're curious ("why?", for starters), so I'd suggest to check the null safety documentation (quick read).
This being said, your code now changes:
(1) We must check if val is nullable, before accessing it. We can either use ! or .? to safely access it; note: the null check operator ! is the least safe null operator, it's likely that it will result in run time exceptions.
validator: (val) {
val==null || val?.isEmpty || val?.length<3
? "Enter Username 3+ characters"
: null
}
(2) I can't infer which method / variable can be null by myself
(3) It depends on what you're trying to do, but I guess that you're trying to implement the Firebase authentication process, in which your user can and should be null before authenticating. Therefore, your function should accept a nullable user value (User?). In there, we do the usual null check and we add a ! operator to promote its value in case user is not null. As aforementioned, Dart isn't always able to infer nullability of variables.
MyUser _userFromFirebaseUser(User? user) {
return user==null ? null : MyUser(userId: user!.uid);
}
Note how using a null-check ! here is perfectly safe, only because you just checked its nullability in the same line (nonetheless, keep a wise-eye when you refactor this).
EDIT. (4)
I can't infer where exactly your exception is fired, but since you want to validate your form, then here's my code from a project of mine:
// inside "saveForm()"...
var currentState = this._formKey.currentState;
if (currentState == null)
return; // this just means something went wrong
if (!currentState.validate()) return; // todo if invalid, handle this, maybe show a snackbar and stuff...
Note how the variable currentState is now promoted to be non-nullable WITHOUT using the null check operator !, which is just good practice (avoid using ! whenever possible, PREFER using null-aware operators, such as ?. or ??, or ?=)
Being empty is not the same as being null. So before you can check an object is empty, you need to check against null first.
if (obj != null && !obj.isEmpty) {}
With reference to the recent changes regarding FirebaseUser to User. FirebaseAuth.instance.currentUser() is not found at all (while throughing error "The expression doesn't evaluate to a function, so it can't be invoked." The solution to that however was to simply remove the paranthesis as FirebaseAuth.instance.currentUser. But now we have another error that it isn't a future type i.e "The argument type User can't be assigned to the parameter type Future<Object?>?". Following is my code block.
return FutureBuilder(
future: FirebaseAuth.instance.currentUser,
builder: (ctx, futureSnapshot) => ListView.builder(
reverse: true, // So that 1st message goes to last.
itemCount: chatDocument.length,
itemBuilder: (ctx, index) => MessageBubble(
message: chatDocument[index]['text'],
isMe: chatDocument[index]['userId'],
),
),
);
In the above code block I intend to provide future to my `FutureBuilder`. In summary previously `FirebaseUser` object did return a future, but probably `User` doesn't anymore. How may I handle this case? Thanks in advance.
I don't typically do that with a FutureBuilder. Once you have a user, you don't need to async it.
final FirebaseAuth_auth = FirebaseAuth.instance();
final User? user;
user = _auth.currentUser;
Then, if user != null ....create your ListView else, return a CircularProgressIndicator or whatever.
Look up Net Ninja for some nice videos for getting yourself set up with all that, just having a stream based on userChanges() for your project. More robust setup.
Im getting this error in my dart code. If I delete coverImage widget , It gives error for other snapshat.data`s widget
My Error
Exception caught by widgets library
The following NoSuchMethodError was thrown building FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(dirty, state:
_FutureBuilderState<DocumentSnapshot<Map<String, dynamic>>>#45e11):
The method '[]' was called on null.
Receiver: null
Tried calling:
The way Im using data.
image: DecorationImage(
fit: BoxFit.cover,
image: (snapshot.data['coverImage']).isEmpty
? AssetImage('assets/background.png')
: NetworkImage(snapshot.data['coverImage']),
),
My flutter doctor
Hi in your switch statement you are not doing anything, so you are not filtering in which state the futurebuilder is and thus trying to access the data when its not already completed:
return FutureBuilder(builder: ( context, snapshot) {
if(snapshot.hasData){
return ListView();
}else if (snapshot.hasError){
return Center(child:Text(snapshot.error.toString()));
}
return Center(child: CircularProgressIndicator());
}
Here the three principal states are taken care of.
It's probably your snapshot data is null
Maybe you should handle it with ? or == null
image: (snapshot?.data['coverImage']).isEmpty
or
final dataCoverImage = snapshot.data['coverImage']
image: (dataCoverImage == null) || (dataCoverImage.isEmpty)
? AssetImage('assets/background.png')
: NetworkImage(snapshot.data['coverImage']),
check if ['coverImage'] is there in your database your error shows that this field is not in your database
you can check in the code by
(snapshot.data['coverImage']).isEmpty || snapshot.data['coverImage'] ==null)
When the app starts it throws an Exception caught by widgets library in a console:
======== Exception caught by widgets library ======================================================= The following NoSuchMethodError was thrown building
StreamBuilder<List<Entry>>(dirty, state:
_StreamBuilderBaseState<List<Entry>, AsyncSnapshot<List<Entry>>>#97504): The getter 'length' was called on
null. Receiver: null Tried calling: length on `itemCount: snapshot.data.length`,
But the whole app nonetheless works in emulator. What is the reason of that?
StreamBuilder<List<Entry>>(
stream: entryProvider.entries,
builder: (context, snapshot) {
return ListView.builder(
itemCount: snapshot.data.length, // the error is here
itemBuilder: (context, index) { ...
When the stream is busy loading data, snapshot.data will be null until the ConnectionState of StreamBuilder is ConnectionState.done.
There are a few fixes you can try.
1. Use if (snapshot.hasData)
This will ensure that snapshot.data is used only when it is not null
2. Use Null operator
When trying to get the length of snapshot.data, try this
snapshot?.data.length ?? 0
3. Check ConnectionState
You can also check the ConnectionState of StreamBuilder but you might still need to use the first solution i.e, snapshot.hasData, normally I
would prefer one of the above solutions.
Use snapshot.data.size instead of .length.
solved the problem by replacing StreamBuilder<Object> with StreamBuilder<QuerySnapshot>. by default the StreamBuilder comes in this form StreamBuilder<Object>
this will work 100%