Dart null safety !. vs ?- - flutter

what is the difference exactly between
String id = folderInfo!.first.id; //this works
and
String id = folderInfo?.first.id; //this is an error
I know ?. returns null when the value object is null but what does the !. return?

?. is known as Conditional member access
the leftmost operand can be null; example: foo?.bar selects property bar from expression foo unless foo is null (in which case the value of foo?.bar is null)
In your case, String id means id can not have null value. But using ?. can return null that's why it is showing errors.
!. is use If you know that an expression never evaluates to null.
For example, a variable of type int? Might be an integer, or it might be null. If you know that an expression never evaluates to null but Dart disagrees, you can add ! to assert that it isn’t null (and to throw an exception if it is).
More and ref:
important-concepts of null-safety and operators.

The Assertion Operator (!)
Use the null assertion operator ( ! ) to make Dart treat a nullable expression as non-nullable if you’re certain it isn’t null.
In other words !. will throw an error if the value is null and will break your function and as you know ?. will return null with no interruption.

The ! throws an error if the variable is null. You should try to avoid this if possible.

If you’re sure that an expression with a nullable type isn’t null, you can use a null assertion operator (!) to make Dart treat it as non-nullable. By adding ! just after the expression, you tell Dart that the value won’t be null, and that it’s safe to assign it to a non-nullable variable.
In your first case, you define id not nullable but when you set nullable value then throw error.
String id = folderInfo?.first.id;
In 2nd case, when you use assertion operator (!), it actually tell compiler that it must be non nullable.

Related

What does the '!' at the end of my code do?

Text(locations[index].location!)
without the '!' I get the next error:
The argument type 'String?' can't be assigned to the parameter type 'String'
Thanks in advance!
locations[index].location can return null, using ! we are saying, the value of it won't be null. Text widget doesn't accept null value.
It is better to do a null check 1st on nullable data like
if (locations[index].location != null) Text(locations[index].location)
or you can provide default value
Text(locations[index].location ?? "got null")
You can also do
Text("${locations[index].location}");
The exclamation mark (!) in Dart tells the code that you are sure this variable can never be null. It is an unsafe way of dealing with variables that may be null.
In your case, the type of the variable is String?, which means that it may be null or a String.
To safely unwrap a nullable variable, it is advised to do the following:
if (locations[index].location != null) {
//Do your logic here
}
Null Safety Documentation
It means it is a nullable type, which means it can be initialized without any value.

The argument type 'String?' can't be assigned to the parameter type 'String' in flutter for shared prefrances

so I am using shared preferences in a flutter app and I get this error :
The argument type 'String?' can't be assigned to the parameter type 'String'
and here is the code:
if (result != null) {
SharedPreferenceHelper().saveUserEmail(userDetails.email);
}
the error is userDetils.email can someone pls help
A picture of what it shows
Those are two different types. You need to coerce String? to String either by the null coercion operator: userDetails.email! or by giving it a default value if it's null: userDetails.email ?? ''
After looking into the image posted the line 30 declaration states that:
User? userDetails = result.user;// Which potentially means that variable userDetails could be null
Where as the class User details are not shared but peaking into the issue I am pretty sure the class User has a email parameter whose declaration is as includes it's datatype as String? email something like this with prefix of final or late.
In this case what happens is that you have nested level of nullity for accessing email variable out of userDetails object.
Which means:
Case 1=> userDetails is null and email is null.
Case 2=> userDetails is not null and email is null.
Case 3=> userDetails is not null and email is not null.
Meaning both `userDetails` and `email` have a datatype of which defines them to be null at compile time.
Since dart is statically typed language so you need to add in ! after each variable whose datatype is nullable at compile time to allow dart know that the variable has data in it and was assigned a value sometime later in run time.
So to fix this what you need to do is that replace the line below with line 33:
SharedPreferenceHelper().saveUserEmail(userdetails!.email ?? "Some default email");
// if you never want to save null as email pref else use the one below
SharedPreferenceHelper().saveUserEmail(userdetails!.email.toString());
It is sound null safety problem
String? means Whatever variable assigned to Stirng? type it can be null or null value is available
,so make sure to check it null or not by providing userDetils.email?? this means userDetils.email is null or not

I get an error with snapshot.data()["~~~"] flutter

I'm trying to get the value from Firestore with the following code. But I'm sorry I got this error. Help me
DocumentSnapshot snapshot = await FirebaseFirestore.instance.collection("users").doc(user.uid).get();
print(snapshot.data()["location"] as String);
Details of 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 ('!').
I tried various things, for example print(snapshot.data()!['location'] as String);
error code
The operator '[]' isn't defined for the type 'Object'. Try defining the operator '[]'.```
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 ('!').
As you might be able to guess, you are getting an error because if the snapshot has no data, it will return null, which will error. Here are some ways of fixing it:
adding a bang operator (!) (But you say this did not fix the issue?)
print(snapshot.data()!['location'] as String);
note the ! after data(), the bang operator tells dart to ignore a nullable value, this code will work as long as snapshot.data() is not null, of course, this is not safe, because snapshot.data() could be null, so here is an obvious solution:
var data = snapshot.data();
if (data != null) {
print(data!['location'] as String);
}
this should work, because now if data is null, the print statement will simply not run.
adding a ? operator
print(snapshot?['location']);
note the ? after data(), the ? operator will escalate a null value, so if snapshot.data() is not null, snapshot.data()?['location'] will be equal to snapshot.data()['location'], but if snapshot.data() is null, snapshot.data()?['location'] will be equal to null instead of throwing an error.
Adding a ?? operator
print(snapshot.data()?['location'] ?? 'the value was null');
Here, it is necessary to use both the ? operator to escalate the null value and the ?? operator.
The ?? operator will output the value on the left if the value is not null and will output the value on the right if the value on the left is null, so in this case, if snapshot.data() is null, that will escalate the null value, meaning snapshot.data()?['location'] will be null, which in turn means that instead of printing 'null', the ?? operator will print 'the value was null'
So to conclude, if you are sure the value is not null, you can use the bang operator !, if you are not sure, then you can use a combination of ? and ?? to your advantage.
Edit
It looks like adding one of the above solutions still won't fix the issue, here is an updated version that will hopefully fix the new issues?
print((snapshot.data()! as Map<String, dynamic>)['location'] as String);
you need to add null check operator to make sure that receiver is not null.
print(snapshot.data()!["location"] as String);

How to take integer input in dart after the null safety update without using the if block for veriying weather the variable is null or not? [duplicate]

This question already has answers here:
"The argument type 'String?' can't be assigned to the parameter type 'String'" when using stdin.readLineSync()
(3 answers)
Closed 1 year ago.
Every time i need to input certain variable as integer i used to use this below code for that
import 'dart:io';
void main(List<String> arguments) {
int a = 0;
print("Enter a :");
String? x = stdin.readLineSync();
if (x != null) {
a = int.parse(x);
}
}
which is very hectic...very since the null safety was added from Dart 2.12 version.Before it the integer was inputted using this code int n = int.parse(stdin.readLineSync());
can anyone propose to make it smaller...since its hefty..
Since we are using Null Safety by default with Dart 2.12.2.
We also know that int.parse() take a String that cannot be null due to Null Safety.
however int.parse(readLineSync()) can return a int? which is a nullable value by simply adding the The null assertion operator (!) at the end of stdin.readLineSync() as show in code below
import 'dart:io';
void main(List<String> arguments) {
print("Enter a :");
int? a = int.parse(stdin.readLineSync()!);
}
The null assertion operator (!)
If you’re sure that an expression with a nullable type isn’t null, you can use a null assertion operator (!) to make Dart treat it as non-nullable. By adding ! just after the expression, you tell Dart that the value won’t be null, and that it’s safe to assign it to a non-nullable variable.
note:-If you’re wrong, Dart throws an exception at run-time. This makes the ! operator unsafe, so don’t use it unless you’re very sure that the expression isn’t null.
Hope you find this useful...(☞゚ヮ゚)☞

Flutter null-safety conditionals in object methods

I'm just working through this whole null-safety mode with my Flutter project and unsure what the difference is with ? and ! in calls to object methods.
For example, the hint was to add a ! conditional. Here's an example I have right now, and I'm unsure if this should be a ? or a ! at the findNbr!.replaceAll().
Future checkItem({String? findNbr}) async {
int? x = int.tryParse(findNbr!.replaceAll('-', ''));
...
Does this mean replaceAll() will not run if findNbr is null?
Or should it be a ? instead? findNbr?.replaceAll()
EDIT: I just noticed I cannot use findNbr?, it's telling String? can't be assigned parameter String.
Or does it mean I say it's not null and run it anyway?
For your information, I have not come close to running my app yet so I have no idea if it even works. But I figure I better know what it's doing before get too much more done. I'm still in the process of converting everything and there's 75-100 dart files. I'm not sure I get the point of it all to be honest, because I just add ? to everything, so its all nullable anyway.
Future checkItem({String? findNbr}) async {
int? x = int.tryParse(findNbr!.replaceAll('-', ''));
...
Does this mean replaceAll() will not run if findNbr is null?
Correct. If findNbr is null, then findNbr! will throw a runtime exception. That would be bad, especially since checkItem's function signature advertises that findNbr is allowed to be null, and therefore it would violate callers' expectations.
Or should it be a ? instead? findNbr?.replaceAll()
EDIT: I just noticed I cannot use findNbr?, it's telling String? can't be assigned parameter String.
You can't use findNbr?.replaceAll(...) because if findNbr is null, then it would be invoking int.tryParse(null), but int.tryParse is not allowed to take a null argument.
What you need to do is one of:
Make findNbr no longer optional:
Future checkItem({required String findNbr}) async {
int? x = int.tryParse(findNbr.replaceAll('-', ''));
...
Allow findNbr to be optional but have a non-null default value:
Future checkItem({String findNbr = ''}) async {
int? x = int.tryParse(findNbr.replaceAll('-', ''));
...
Allow findNbr to be optional but explicitly decide what to do if it is null. For example:
Future checkItem({String? findNbr}) async {
int? x = findNbr == null ? null : int.tryParse(findNbr.replaceAll('-', ''));
...
I'm not sure I get the point of it all to be honest, because I just add ? to everything, so its all nullable anyway.
If you blindly add ? to all types and add ! to all variables, then yes, null-safety would be pointless: doing that would give you the same behavior as Dart before null-safety.
The point of null-safety is to prevent things that shouldn't be null from ever being null. You could have written such code before, but without null-safety, that meant performing runtime null checks (e.g. assert(x != null);, if (x != null) { ... }, or relying on a null-pointer-exception to crash the program if null was used where it wasn't expected). Null-safety means that such checks now can be done at build-time by static analysis, which means that errors can be caught earlier and more completely. Furthermore, whereas previously functions needed to explicitly document whether arguments and return values were allowed to be null (and inadequate or incorrect documentation could be a source of errors), now they're self-documenting in that regard. It's just like using int foo(String s) versus dynamic foo(dynamic s); using strong types catches errors earlier and better describes the function's contract.
I recommend reading Understanding Null Safety if you haven't already done so.
I would like to advice you to use the ! operator, also the called bang operator, as little as possible. You should only use this operator when the dart analyser is wrong and you know for 100% that the value will never be null.
Below is an example of where the dart analyser would be wrong and you should use the bang operator.
// We have a class dog with a nullable name.
class Dog {
String? name;
Dog({this.name});
}
void main() {
// We create a dog without a name.
final dog = Dog();
// We assign the dog a name.
dog.name = 'George';
// The dart analyser will show an error because it can't know if the
// name of the object is not null.
//
// Will throw: `A value of type 'String?' can't be assigned to a
// variable of type 'String'`.
String myDogsName = dog.name;
// To avoid this, you should use the bang operator because you `know` it
// is not null.
String myDogsName = dog.name!;
}
The ? operator simply tells Dart that the value can be null. So every time you want to place a ? operator, ask yourself, can this value ever be null?
The null safety features in Dart are mainly created for helping the developer remember when a value can be null. Dart will now simply tell you when you made a variable nullable in order to force null checks or default values for example.