Can't assign non-nullable type to a nullable one - flutter

error: The argument type 'Future<List<GalleryPictureInfo>>' can't be assigned to the parameter type 'Future<List<GalleryPictureInfo>>?'.
Is this Dart Analysis or me? The project still compiles.
Upd. Added code example
FutureBuilder<List<GalleryPictureInfo>>(
future: derpiService.getListOfImages(),
//other code
);
#override
Future<List<GalleryPictureInfo>> getListOfImages(arguments) async {
List<GalleryPictureInfo> listOfImages = [];
var searchImages = await getSearchImages(tags: tags, page: page);
//adding images to List
return listOfImages;
}
It's something with FutureBuilder actually. I should've mention this.
Upd. "Fixed" with // ignore: argument_type_not_assignable
Looks like a problem with Dart Analysis for now
Upd. Error

It actually is an error which is pretty self explanatory.
The acutal error comes because of null safety in dart.
For ex:
void main(){
var number = getNumber(true);
int parsedNumber = int.parse(number);
print(parsedNumber);
}
String? getNumber(boolean value) {
if (value){
return null;
} else return "1";
}
So here, getNumber function either returns null or "1" depending upon the value of value variable. So, number variable's type is String?.
But the error shall arise in the next line when you try to call int.parse(). int.parse function takes an argument which should be a String but the value passed in the function is of type String?. So if we pass null in int.parse it shall throw an error.
That's why Dart analysis makes it easier to identify such cases by telling us that the value can be null and it might throw.
However the code depends upon your actual code of your project. It says that you are passing Future<List<GalleryPictureInfo>>? which is of nullable type to a function which requires Future<List<GalleryPictureInfo>>. So, before passing the value you might want to check if the value you are passing is not null.
If you are sure that the value can never be null then if for ex: if you are passing a variable called value, you might wanna try someFunctionWhereYouPassValue(value!)
That ! means that you are sure that the value will never be null.
For more details about null safety you can see:
https://dart.dev/null-safety/understanding-null-safety

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

Unable to put function in validator in flutter

class StudentValidationMixin{
String validateFirstName(String value){
if(value.length<2){
return "Name must be at least two characters";
}
}
}
I am trying to use the feature of the container function and when I come to the validator part, I cannot run the code I mentioned above. I'm facing a problem as I wrote below
The body might complete normally, causing 'null' to be returned, but
the return type, 'String', is a potentially non-nullable type.
body: Container(
margin: EdgeInsets.all(20.0),
child: Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText:"Öğrenci Adı",hintText: "Engin"),
validator: validateFirstName,
onSaved: (String value){
student.firstName=value;
},
naturally I get an error in this (validator: validateFirstName) part as well and this is the error I get
The argument type 'String Function(String)' can't be assigned to the
parameter type 'String? Function(String?)?'.
I couldn't find this answer anywhere but I know the answer is hidden somewhere, I finally gave up and wanted to ask here. How do I fix this error? The trainer I learned Flutter can run this function without having these problems.
As you rightly said the answer is hidden somewhere, indeed it is.
Problem:
The body might complete normally, causing 'null' to be returned, but the return
type, 'String', is a potentially non-nullable type.
The argument type 'String Function(String)' can't be assigned to the parameter type
'String? Function(String?)?'.
Reason:
I don't know about "Jack of all Trade" VSC, but, in Android studio, when you hover the cursor over any paramter, a pop-up tells you what type of input it takes.
So, for the paramter validator in TextFormField, the type acceptable in new Flutter versions which support Null Safety is String? Function(String?)? as you can see in the below image:
But, it worked in the (old) video you watched because in versions lower than Flutter 2.0 (Null Safety), the type was String Function(String) as you can see in the image below:
Now, you can figure out the error you're getting is indeed related to versions. Because, you're trying to use the old type in the new version as with this function:
class StudentValidationMixin{
String validateFirstName(String value){
if(value.length<2){
return "Name must be at least two characters";
}
}
}
Solution:
Change your validator() type as below:
class StudentValidationMixin{
String? validateFirstName(String? value) {
if(value.length<2){
return "Name must be at least two characters";
} else {
return null;
}
}
}
See, what we did there? We changed the return type to nullable, which means the value can be null and it should be in case when the validator validates the string correctly. As what it returns is the error in validation, and when there's no error, null should be returned.
Adding the ? mark means telling the compiler that the particular variable's value can be null and of type given. For example The value of int? count can be either integer or null, whereas the value of int count can only be an integer and will produce NullPointerException if it isn't an integer.
Also, comes with NullSafety is the exclaimation mark ! which tells the compiler that even when the variable was declared nullable, at this point, the value is not null. For ex. variable declared as int? count, value entered into it and when you use it. use it as count! to tell the compiler, at this point, there's a value in it.

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.

The argument type 'String?' can't be assigned to the parameter type 'String'

when I upgrade my flutter to 2.0.1, shows this error:
The argument type 'String?' can't be assigned to the parameter type 'String'.
this is my code:
enum SubStatus {
SUB,
UNSUB,
}
extension ResponseStatusExtension on SubStatus{
static const statusCodes = {
SubStatus.SUB: "sub",
SubStatus.UNSUB: "unsub",
};
String? get statusCode => statusCodes[this];
}
This is how to use it:
String url = "/post/sub/source/" + subStatus.statusCode + "/" + channelId;
this is the error UI:
what should I do to fix it? I tried to return String but in the enum code tell me should return String?:
what should I do?
Change the return type of statusCode to String and provide a default value.
String get statusCode => statusCodes[this] ?? '';
When accessing a map, there is a chance that you will get a null return value if the key does not exist in the map. Simply providing a default value will allow this code to compile. That default value should never be used unless you add something to the enum without adding a value to the map as well.
Edit:
After the comment from #Christopher Moore, I realized my mistake. So, I am going to directly use his solution over here as it is the correct one.
This is because of the new null-safety feature of Dart.
You will need to make the following change in the code and it will work:
String get statusCode => statusCodes[this] ?? '';
With new null-safety rules, the following data-type? x, the data type is followed by a question mark, means that the value x can be null. However, without the '?', it means that data-type x, it cannot be null.
So, basically String and String? are two different data types. That is why you get the error.
You can learn more here.
restart analysis server
add !
like this
subStatus.statusCode!

Dart, Identifier with exclamation mark in the back

Recently I have been developing mobile aplication with flutter, when I looking at the source code for TickerProvider I see these lines:
mixin SingleTickerProviderStateMixin<T extends StatefulWidget> on State<T> implements TickerProvider {
Ticker? _ticker;
#override
Ticker createTicker(TickerCallback onTick) {
...
_ticker = Ticker(onTick, debugLabel: kDebugMode ? 'created by $this' : null);
return _ticker!;
}
...
}
I'm interested with this line:
return _ticker!;
I have seen boolean identifier with exclamation mark in the front meaning that it will return the opposite value of it, but I never see this one. Can someone tell me what this does?
It's part of the null safety that Dart have.
You can read about it here
If you’re sure that an expression with a nullable type isn’t null, you can add ! to make Dart treat it as non-nullable
Example:
int? aNullableInt = 2;
int value = aNullableInt!; // `aNullableInt!` is an int.
// This throws if aNullableInt is null.
For betrer undestanding (by analogy with the action of the algorithm itself).
This operator acts as the following inline internal function (at least similarly):
T cast<T>(T? value) {
if (value == null) {
throw _CastError('Null check operator used on a null value');
} else {
return value;
}
}
P.S.
Forgot to add.
Based on the error messages that are generated at runtime, we can conclude that this operator is called the Null check operator, which may mean that it checks the value for null and throws an exception if the value is null.
No magic!