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

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.

Related

Dart null variable creation

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.

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

The name 'string' isn't a type and can't be used in an 'is' expression

During unit testing of a function returning different types of objects, I need to check if the type of returned object is the same as expected. Therefore, I need to pass multiple classes inside a variable. Then I need to use this variable with the is operator to check types.
final string = String;
assert('foo' is string);
But I am getting
error: The name 'string' isn't a type and can't be used in an 'is' expression.
I read somewhere that a library called Dart:mirrors can solve this problem but I haven't seen an actual example.
In unit testing, you know the expected answer. There shouldn't be a need to make your types variables.
Instead, just assert with the strong typed
assert('foo' is String);
I found the answer. The trick to create an instance of the type that I want to assert, then use runtimeType property.
If a class is called User from a.dart and another one is also called User from b.dart, runtimeType won't be the same
final string = 'anything'.runtimeType;
assert('foo'.runtimeType is string);

Error in flutter : The method 'text' was called on null. Receiver: null while localization [duplicate]

I have some code and when I run it produces an error, saying:
NoSuchMethod: the method 'XYZ' was called on null
What does that mean and how do I fix it?
Why do I get this error?
Example
As a real world comparison, what just happened is this conversation:
Hey, how much gas is left in the tank of the car?
What are you talking about, we don't have a car.
That is exactly what is happening in your program. You wanted to call a function like _car.getGasLevel(); but there is no car, the variable _car is null.
Obviously, in your program it might not be a car. It could be a list or a string or anything else really.
Technical explanation
You are trying to use a variable that is null. Either you have explicitly set it to null, or you just never set it at all, the default value is null.
Like any variable, it can be passed into other functions. The place where you get the error might not be the source. You will have to follow the leads from the actual null value to where it originally came from, to find what the problem is and what the solution might be.
null can have different meanings: variables not set to another value will be null, but sometimes null values are used by programmers intentionally to signal that there is no value. Databases have nullable fields, JSON has missing values. Missing information may indeed be the information itself. The variable bool userWantsPizzaForDinner; for example might be used for true when the user said yes, false when the user declined and it might still be null when the user has not yet picked something. That's not a mistake, it's intentionally used and needs to be handled accordingly.
How do I fix it?
Find it
Use the stack trace that came with the error message to find out exactly which line the error was on. Then set a breakpoint on that line. When the program hits the breakpoint, inspect all the values of the variables. One of them is null, find out which one.
Fix it
Once you know which variable it is, find out how it ended up being null. Where did it come from? Was the value never set in the first place? Was the value another variable? How did that variable got it's value. It's like a line of breadcrumbs you can follow until you arrive at a point where you find that some variable was never set, or maybe you arrive at a point where you find that a variable was intentionally set to null. If it was unintentional, just fix it. Set it to the value you want it to have. If it was intentional, then you need to handle it further down in the program. Maybe you need another if to do something special for this case. If in doubt, you can ask the person that intentionally set it to null what they wanted to achieve.
simply the variable/function you are trying to access from the class does not exist
someClass.xyz();
above will give the error
NoSuchMethod: the method 'xyz' was called on null
because the class someClass does not exist
The following will work fine
// SomeClass created
// SomeClass has a function xyz
class SomeClass {
SomeClass();
void xyz() {
print('xyz');
}
}
void main() {
// create an instance of the class
final someClass = SomeClass();
// access the xyz function
someClass.xyz();
}

Why my method fails with the "boolean expression must not be null" exception, but SharedPreferences.getBool() don't?

I'm new to Dart and I'm wondering why I can't return null instead of a bool value in a method like this:
bool getFoo(SharedPreferences sp) {
return sp.getBool('foo');
}
But the SharedPreferences.getBool() method can return null:
bool getBool(String key) => _preferenceCache[key];
Both methods have the same return value type-hint. But the Dart's standard lib method can return null. When I call getFoo(prefs) I'm getting the exception Failed assertion: boolean expression must not be null in my method, not in the Dart's std lib method. Why? What's the difference? Why two methods with the same type-hint definition behave differently?
There is no difference in how the two functions treat the return of null.
Currently, all Dart functions with a bool return type can return null because all Dart types are nullable.
That doesn't mean that you can use null as a boolean, just as you can't call string methods on a null value with static type String. The null value represents the absence of an actual value, so if you end up using null in a condition (if, while, ?:) then you will get the error that you are now seeing.
Dart does not have coercion between different types, and you cannot treat a non-boolean value as a boolean, not even null. Obviously the language could have chosen to do so, say treat all non-true values as false (like it did in Dart 1, before the stricter type system of Dart 2), but it's actually fairly arbitrary whether null should mean true or false, so instead null means the absence of a boolean value, and therefore not being able to choose a branch of an if statement. This is consistent with all other places where null can flow, but its an error if it does and you try to use the value.
When Dart gets non-nullable types, then the conditions will be required to be (statically typed as) non-nullable booleans. This ensures that a null value cannot accidentally flow to a position where it is attempted used.
If you know that your result might be null, you can always substitute a default value explicitly: if (maybeBool ?? false) ...
Again, with non-nullable types, you will have to do that, if you haven't handled the null value earlier.
The issue was in the if statement. It doesn't accept nulls and doesn't cast null to boolean false. It requires a boolean value. I came to Dart from PHP and JavaScript so this moment was very unobvious for me. And I didn't read documentation carefully: https://dart.dev/guides/language/language-tour#if-and-else.
I actually can't see any profits from this strictness like in strictly typed languages while I can return the null result for a scalar type. https://github.com/dart-lang/sdk/issues/22 - this is the very early issue that Dart lang developers still implementing, but promise to finish it soon.