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

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.

Related

In dart what is the difference between ? and ! for nullable types?

I am new to Dart and Flutter.
In dart what is the difference between using ? and ! for null-able types?
validator: ((value) {
if (value?.isEmpty) {
return "Field is required";
}
return null;
}),
validator: ((value) {
if (value!.isEmpty) {
return "Field is required";
}
return null;
}),
Thanks in advance!
Good topic about it : What is Null Safety in Dart?
But in short, you use "?" when you want to allow the value to be null and use it accordingly, like this:
String? test;
if (test?.isEmpty == true) { // And is not null, but you don't need to check it
// If null, will never pass there but without error
}
And use "!" when you want to be sure to have a non nullable value, like this:
String? test;
if (test!.isEmpty == true) { // Will throw an error
...
}
the difference between the two,one can be null initially, but the other cannot.
I hope you understand in the example below.
To specify if the variable can be null, then you can use the nullable type ?
operator, Lets see an example:
String? carName; // initialized to null by default
int? value = 36; // initialized to non-null
value = null; // can be re-assigned to null
Note: You don’t need to initialize a nullable variable before using it. It is initialized to null by default.
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.
int? someValue = 30;
int data = someValue!; // This is valid as value is non-nullable
In the above example, we are telling Dart that the variable someValue is null, and it is safe to assign it to a non-nullable variable i.e. data
I hope you understand????
As for your example;
if you notice, the validator {String? value} value can initially be null. but the only difference between both works in the code you wrote will be the running cost. '?' it will cost some time when you define it again. because it is already stated in the function that it will be null as a start.
It's a good question and the answer is here as a person.
'?' it means it will get value later or it can be null( initially or at any instance) for example
String? carName;
'!' it means you are going to receive the value and it can not be null. it will check the value if the value is null it will give exception.
have a look on example for clear difference:
List? blocks;
...
// you are not sure blocks variable is initialized or not.
// block is nullable.
final Block? block = blocks?.first;
// you are sure blocks variable is initialized.
// block is not nullable.
final Block block = blocks!.first;
hope you got it if yes accept the answer or comment me if you have question

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

Dart null safety !. vs ?-

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.

Method 'replaceFirst' cannot be called on 'String?'

Error: Method 'replaceFirst' cannot be called on 'String?' because it is potentially null.
Try calling using ?. instead.)
.replaceFirst(r'$selectedRowCount', formatDecimal(selectedRowCount));
As Saffron-codes says, you cant do a replaceFirst on a 'String?' variable since it can be null, and dart is null safe.
There's two options for you to do. You can either make the variable a 'String' instead, if you do this you'll have to give it a value when initiating it:
String variableName = ''
Instead of:
String? variableName
You could also do a null-check (adding a questionmark before .replaceFirst) when calling replaceFirst, this is what it suggests doing in the error message 'Try calling using ?. instead.':
variableName?.replaceFirst(r'$selectedRowCount', formatDecimal(selectedRowCount));
Add the ! operator before . to make it non-nullable
!.replaceFirst(r'$selectedRowCount', formatDecimal(selectedRowCount));

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);