Dart null variable creation - flutter

I just started learning Dart. There is some problem when I am creating a null variable. When I type
String someVar;
it throws an error but when i type
dynamic someVar;
it doesn't. I tried doing alternative methods mentioned in Dart's doc but even those methods do not seem to work until i have a dynamic var type. Can anyone tell me what is it?

Dart has a feature called null safety, so when you define something which might have a null value, you have to use ?.
In your code above, try something like String? somevar;
If you are going to initialize the variable later, then define late String somevar;

If you have null safety on String someVar; will give you an error because it cannot be null.
If u want a variable to be a nullable string, use String? someVar.
Try avoiding the use of dynamic because it will allow for the type to not be fixed. This can potentially cause the accidental assigning of a value with a type you are not expecting.

Related

The method 'compareTo' can't be unconditionally invoked because the receiver can be 'null'

How to fix this? Error Message: The method 'compareTo' 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 ('!').
Second Error: The argument type 'Object?' can't be assigned to the parameter type 'Object'.
How to fixed it?
It looks like you lack basic understanding about null safety features.
String? basically means that it's a String that can be null. This can be done with any type. A question mark ? at the end of the type name makes it nullable, and if it isn't there it can't be null.
The language is designed in such a way that you can't assign any objects that are nullable to variables that aren't or use methods of objects that might be null.
There are several ways to handle this.
1) don't make them nullable in the first place.
In your example, whatever the object is, it must have some field declared as String? name. Just remove the ? if possible. There's a good chance it will make other errors pop up, but it should be solvable, at least in the case where you don't allow it to be null. If for whatever reason you need it to be nullable this is not a solution.
2) tell the compiler that you are sure it's not null in this situation
This is done by adding ! at the end of the variable. In your example that would be:
b.name!.compareTo(a.name!)
This is probably the easiest solution but the program will throw errors at runtime if they do happen to be null
3) provide a fallback value using ??
?? basically is an operator that returns the left side if it's not null and otherwise the right side. You can use this to your advantage to provide fallback values. In your example you could do:
(b.name ?? '').compareTo(a.name ?? '')
This way it takes empty string in case the name is missing. This would be a safer option compared to option 2.
4) conditional calling using ?.
Maybe not applicable in your situation but good to know anyway. Let's say some class A has the method getName and you have an object a of type A? and this code:
String? b = a.getName();
this is not allowed because a can be null. But you can write this:
String? b = a?.getName();
This basically mean that it executes getName() and assigns it to b when a is not null or just assigns null otherwise, which is possible because b is allowed to be null here. Therefore, this is NOT possible
String b = a?.getName();
Now b is defined as not being nullable and since the assignment possibly can provide null you are not allowed to.

Correct way to handle variable initialisation in flutter? Late or make it nullable?

Hello good folk of stack overflow, teaching myself flutter and have come across null safety.
I believe I 'understand' the difference between making a variable nullable and telling dart I will initialise later. But is there a correct way to do it?
In what instance would you choose late over making a variable nullable?
Consider the small class I have below, I've chosen to use the late method (admittedly I don't really know why) Would you chose this same method or should I be making the variables nullable?
Thanks!
class Quote{
late String text;
late String author;
Quote(String text, String author){
this.text = text;
this.author=author;
}
}
There is also a third solution and forth (done in two ways) solution here.
You can add a non-null default value to the field.
String text = '';
But I would go here with initializing the fields directly in the constructor argument list.
class Quote {
String text;
String author;
Quote(this.text, this.author);
}
...or using a constructor initializer list:
class Quote {
String text;
String author;
Quote(String text, String author)
: text = text,
author = author;
}
Using the forth solution (second and third code snippet) you can also make those fields final and the constructor constant.
Lastly, quoting the documentation Classes - Language Tour | Dart:
Instance variables can be final, in which case they must be set exactly once. Initialize final, non-late instance variables at declaration, using a constructor parameter, or using a constructor’s initializer list (...)
If you need to assign the value of a final instance variable after the constructor body starts, you can use one of the following:
Use a factory constructor.
Use late final, but be careful: a late final without an initializer adds a setter to the API.
You mentioned the answer in the question too. If your business logic requires to check if a value is null use nullable variable and if you want some definite value then use late. For example you may not know if you will get a response from an api as expected. So better to define as nullable.

I have few questions relating to the null safety feature which is offered by dart or flutter

I have few questions with regards to the null safety feature offered by Flutter/Dart.
Is it mandatory to make use of the null safety feature for flutter projects?
If I don't make use of the null safety feature, will I still be able to make use of all the existing and latest flutter widgets, with all the latest functionality they have got to offer? What I mean to say is, is there any specific functionality that is only available when the null safety feature is enabled.
What would be the major disadvantages, I could encounter, apart from the null check, if I don't make use of the null safety feature for the flutter projects?
Even if the code is correct, I find that the null safety feature would keep throwing the null check operator error, which is very annoying.
Could anyone please help with answering my queries, as I find this null safety to be very confusing and annoying. I did go through few videos but still, I'm not convinced.
Thank you so much for your help in advance.
Null safety can be overridden
Yes, you should still be able to make use of the new flutter widgets.
If you use don't null-safety, it will be slower
This is more like a statement than a question
Understanding Null Safety.
Is it mandatory to make use of the null safety feature for flutter projects?
No, you can still use the previous SDK constraints to not comply with NULL safety rules
environment:
sdk: ">=2.11.0 <3.0.0"
If I don't make use of the null safety feature, will I still be able to make use of all the existing and latest flutter widgets, with all the latest functionality they have got to offer? What I mean to say is, is there any specific functionality that is only available when the null safety feature is enabled.
Yes provided you set the environment as mentioned above or you can also specify at the top of your Dart file to disable null checks for that file.
// #dart=2.9
What would be the major disadvantages, I could encounter, apart from the null check, if I don't make use of the null safety feature for the flutter projects?
Note that eliminating null is not a goal. There’s nothing wrong with null. On the contrary, it’s really useful to be able to represent the absence of a value. Sometimes indicating absence is really important. It is not null that is bad, it is having null go where you don’t expect it that causes problems. So to avoid such crashes Dart migrated to Sound NULL Safety.
Even if the code is correct, I find that the null safety feature would keep throwing the null check operator error, which is very annoying.
You can definitely make some types NULL with the handy ? null-aware operator. For eg, you can make your String as String? provided indicating absence is really important and it won't cause problems in the future program flow.
Adding ! (null assertion operator )after any expression is equivalent to saying that "Hey Dart ! trust me that this value will never be null".
Initially, it might trouble you a lot. But remember, it's worthwhile migrating your apps to Sound Null Safety.
Further Reading -
https://dart.dev/null-safety
Why NULL Safety ?
example:
class Animal {
Dog dog;
}
class Dog{
String name;
}
Operator "!":
If you allow it to be null and allow it to throw an exception.
main(){
Animal animal = Animal();
print(animal.dog!.name); // throw exception dog is null
}
Operator "?"
If you want it will do nothing if the current parameter is null
main(){
Animal animal = Animal();
print(animal.dog?.name); // output emplty
}
You can give a replacement value of the parameter if the current value is null
main(){
Animal animal = Animal();
print(animal.dog?.name ?? "The kiki"); // output "The kiki"
}
The function required not null
fun getName(String name){
print(name);
}
main(){
String? name = null;
getName(name); // throw an exception because the required the name argument is not null
}
The function allows null
fun getName(String? name){
print(name);
}
main(){
String? name = null;
getName(name); // output null
}
Null safety in the Constructor
Use required operator
class Animal {
String? name;
String age;
Animal({this.name,required this.age}); // The age argument not allowed to be null so you must add the required operator first
}
or use positional arguments constructor
class Animal {
String? name;
String age;
Animal(this.age, {this.name}); // age is positional argument
}
or use default value constructor
class Animal {
String? name;
String age;
Animal({this.name, this.age = "18" }); // age is positional argument
}

String? - which means the question mark when initializing the variable in flutter

in the code example i found something like this:
String? selectedNotificationPayload;
which means the question mark next to the type of the String variable
It means the type is NullableString. This works for Flutter 2 and above due to null-safety in dart. It basically means the value stored can be a null.
So, String? foo; allows null but String bar; does not allow null.
https://dart.dev/codelabs/dart-cheatsheet
https://dart.dev/null-safety

Understanding " ! " Bang Operator in dart

I declared a callback method inside a Stateful class like:
final void Function(int index)? onSelected;
MyBottomNavigationBar({#required this.onSelected});
and called using widget.onselected inside state class like:
widget.onSelected!(_selectedIndex);
But I'am not able to understand the actual use of ! Bang operator. I can't initialize widget.onSelected in constructor without giving ? during declaration.
My main question is "How ! bang operator is handling the null values? What's the use of it ?
The Bang operator does nothing more than tell Dart that even if we have defined some variable as a Nullable type, it will definitely not be null.
Dart's Nullable safety and Flow Analysis are here to make the developer's life easy by avoiding runtime error and catching them at compile-time itself.
When you define,
final void Function(int index)? onSelected;
You are telling dart that this variable may or may not be assigned a value and thus it may or may not be null.
Now, whenever you try to use it like this,
widget.onSelected()
Dart will warn you that, this is a Nullable typed variable hence take extra care.
If Dart didn't tell you this before hand, then you would've realized it after you ran the app and it crashed while trying to call the function.
Now, since Dart has warned you that you cannot use it like that, there are two ways to approach it.
Put a null check before using it. This way we are avoiding runtime errors.
var onSelected = widget.onSelected;
if (onSelected != null) onSelected(_selectedIndex);
This creation of a new local variable is necessary since Dart's flow analysis only works on local variable null checks and not class level variable null checks.
Use the bang operator,
widget.onSelected!(_selectedIndex)
Now the issue with this is that, you are just assuring Dart that it will never be null, but if it were actually null, it will still result in a runtime crash.
So, the Bang operator is just a way to bypass Dart's flow analysis when you have to access a nullable typed variable.
Hope this clears at least a bit of your doubt.
The bang operator works like an assert statement but in production mode too.
Let's say, this is your function.
final void Function()? foo;
You can't call it directly
foo(); // Error
Here comes a bang operator, which actually says that Dart I take the full responsibility that this function isn't null, let me proceed with the call.
foo!(); // No error
This is essentially equal to doing:
(foo as Function())();
Note:
You will run into an error if foo was null. A good approach is to check for nullability using a local variable and proceed to the call.
final f = foo;
if (f != null) {
f();
}