Assignment of null to File variable in Flutter - flutter

How can I assign null to File variable. I got error when assigning null to File variable.
File myImage=null;
(myImage==null)?
CircleAvatar(
backgroundImage:AssetImage('assets/user_new.png'),
backgroundColor: Colors.cyanAccent,
radius: 70,
)
:
CircleAvatar(
backgroundImage:FileImage(myImage),
backgroundColor: Colors.cyanAccent,
radius: 70,
)

Sound null safety is available in Dart 2.12 and Flutter 2.
When using variables you declare are non-nullable by default and to make them nullable you have to use ? after datatype.
example:
int? i = null
In your case, it will be
File? myImage=null;
and you can use it like below:
(myImage==null)?
CircleAvatar(
backgroundImage:AssetImage('assets/user_new.png'),
backgroundColor: Colors.cyanAccent,
radius: 70,
)
:
CircleAvatar(
backgroundImage:FileImage(myImage!),
backgroundColor: Colors.cyanAccent,
radius: 70,
)
Here when using myImage you will use ! to tell a program that myImage will not be null.
Note: We should avoid using ! wherever possible as it can cause a run time
error but in your case, you are already checking for the null using a
ternary operator so you can safely use !.

I suppose you have nullsafety enabled. With nullsafety a variable declared without a ? cannot be null. To fix your issue do the following.
File? myImage = null;

In Flutter null safety is a thing.
With it, no variables can be null if they haven't got a ?. Add a question mark to your File declaration, as:
File? myImage = null;
Down in your code, you will need to check if myImage is null (since now it can be) if you want to assign it to the backgroundImage parameter. You have 2 choices for this:
backgroundImage:FileImage(myImage!) //Null check: Exception throw only if null
backgroundImage:FileImage(myImage ?? _anotherWorkingFile) //If: use another standard file if null

Related

Dart: How to properly handle null-safety?

I have upgraded my project to null-safety and it's a bit confusing, because if I wrap into a
if(someObject.field != null) {
doSomething(someObject.field); // error, can't assign String? to String
}
a method call that requires a not-nullable property and my variable I am trying to pass is nullable, then I get a type error that I cannot assign a nullable value to a not-nullable type.
But when I do
String? someObjectField = someObject!.field;
if(someObjectField != null) {
doSometing(someObjectField); // Can assign
}
it works as expected.
doSomething = (String foo) {}
For example:
class Person {
final String name;
Person(this.name);
}
Function test = () {
Map<String, String?> pers = {
'name': 'John',
};
if(pers['name'] != null) {
Person(pers['name']); // Error, even if it will be never executed
Person(pers['name'] as String); // no error
Person(pers['name']!); // no error
}
};
And if I do something like:
if (widget.event != null && widget.event.featuredImage != null)
Then it complains in the second statement that the receiver (widget.event) can be null and I need to use !, but the second statemen should never execute and it should never cause a runtime exception.
So I need to modify it to:
if (widget.event != null && widget.event!.featuredImage != null)
But then when I try to use a nested widget inside Flutter, then even if I use the if as wrapper I still need to add ! everywhere
Stack(
children: [
// Add Container with image only when event and futured image are not null
if (widget.event != null && widget.event!.featuredImage != null) ...[
Container(
height: 250,
decoration: BoxDecoration(
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(widget.event!.featuredImage!), // here i Need to use ! to satisfy the compiler
),
),
),
],
],
)
Alternatively I can extract the variable into another one String? image = widget.event!.featuredImage then modify the if statement to if(image != null) and use the widget like NetworkImage(image) which works as expected.
Compared to TypeScript which detects if I checked for null in a condition above, this makes no sense to me.
Longstory short, even if I check for null value to render/not-render a component, I still need to use !.
Is there something obvious that I am missing?
Thank you in advance
Since you compared it to TypeScript, yes, you are missing something.
Typescript is a mess that works in a very limited environment and "works" is grossly overstated. For example you could write a method in typescript that takes a string and then at runtime find out it's not actually a string, surprise, it's a completely different type. The joys of JavaScript. Calling TypeScript "type safe" is correct compared to JS and ridiculous compared to actually compiled languages.
So you are missing the fact that the Dart compiler can guarantee that something is not null once you checked it. To do that, it needs additional constraints. For example, you could have getters that do not return the same value every time you call them. Your call for example could easily return different values between the first and second call, depending on the code of the getter. Or you could use inheritance and polymorphism to build some even more problematic constructs. See here for an interesting example. So you need to have a local variable, that is guaranteed to have the same value, unless explicitely changed.
Your example of if (widget.event != null && widget.event.featuredImage != null) could easily be modified to:
final image = widget?.event?.featuredImage;
Stack(
children: [
// Add Container with image only when event and futured image are not null
if (image != null) ...[
Container(
height: 250,
decoration: BoxDecoration(
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(image),
),
),
),
],
],
)
Yes, you have to implement some tiny bit of logic, you cannot just slap ? and ! on your code and it runs as before. But once you understood what that little change in logic is, it is pretty easy.

check if null produces errors - can't be unconditionally accessed because the receiver can be 'null'

I wanna check if the Icon doesn't return null and if it returns null then show the SvgPic , or else show the Icon .
Errors:
Too many positional arguments,
The property 'icon' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!').
.
final SvgPicture? svgPic; final Icon? icon;
child: Container(widget.icon == null
? widget.svgPic
: Icon(widget.icon.icon,
color: widget.iconColour)),
),
Too many positional arguments
You didn't add any parameter label in that container
The property 'icon' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!')
You are trying to access the icon property of a nullable, so you need to use ? or !.
Instead of:
Container(widget.icon == null ? widget.svgPic
: Icon(widget.icon.icon, color: widget.iconColour),
),
Use:
Container(child: widget.icon == null ? widget.svgPic
: Icon(widget.icon!.icon, color: widget.iconColour)
),

Flutter null safety - The argument type 'Color?' can't be assigned to the parameter type 'Color'

I changed my SDK version for flutter to min , so that I can fix my code for null safety.
There is one issue that I don't understand,
this line produces the following error:
The argument type 'Color?' can't be assigned to the parameter type 'Color'
border: Border.all(color: Colors.grey[300], width: 1),
but if I change Colors.grey[300] with whatever value that doesn't use [], it will work,
so Colors.grey works perfectly fine.
What should I change here to keep using grey[300]?
Problem:
Color color = Colors.grey[300]; // Error in null-safe mode
When you use Colors.grey[300], you're actually getting the color from a Map which Dart (in null-safe mode) warns you about because that value could be null. See more
Solutions:
There are two solutions for it. One is general and one is only specific to this case.
Use Bang operator (!)
Color color = Colors.grey[300]! // Added '!', error gone
Use shadeXXX on the Color
Color color = Colors.grey.shade300;
You can use 0xFFE0E0E0 for grey[300].
To pick material colors you can use this tool.
To select a specific color from one of the swatches, index into the swatch using an integer for the specific color desired, as follows:
Color selection = Colors.green[400]!; // Selects a mid-range green.
Each ColorSwatch constant is a color and can used directly. For example:
Container(
color: Colors.blue, // same as Colors.blue[500] or Colors.blue.shade500
)
use shade300 like
Color color = Colors.grey.shade300;
You can write
Colors.grey[300]! like this and this will work.

what does ":" mean or do in Dart?

I have been trying to get an clear explanation for what : means in dart.
As far as I can tell it seems so be some kind of operator , but I can't get a clear cut explanation of what exactly it does.
I understand that it gets used to so assign stuff to other stuff , but I am unsure of the specifics.
I have tried googling it , no luck.
I have tried searching through the dart documentation.
https://dart.dev/guides/language/language-tour#operators
I know that it gets used as part of conditional expressions like here:
https://dart.dev/guides/language/language-tour#conditional-expressions
Here are examples of how it gets used:
Example 1 :
class someBloc extends Bloc<someEvent, someState> {
someBloc() : super(someState.initial());
}
Example 2 :
class someClass {
final String requestType;
final String name;
factory someClass.fromJson(Map<String, dynamic> json) {
return SomeClass(
requestType: json['Type'],
name: json['Name']);
}
}
In examples 1 & 2:
The : is used to set a named parameter. For example, let's say I want to create a Card widget. The card widget optionally takes a named parameter called elevation. Therefore, I can do this:
Card(
elevation: 4.0,
)
Another way : is used is for writing quick conditional expressions.
final String isMyListEmpty = myList.isEmpty ?? 'Yes, the list is empty' : 'No, the list is not empty';
In this example, our condition is myList.isEmpty. If this condition is true, the first expression after ?? is returned. Else, if the condition is false, the expression after the : is returned.
It's just an assignment operator. You assign a value to a widget property. For example, Container widget has many properties, like color or height:
Container(
margin: const EdgeInsets.all(10.0),
color: Colors.amber[600],
width: 48.0,
height: 48.0,
),

How to use icon as image

Is there any way to use Icon as image? I'm trying to display background image in CircleAvatar. If no image provided use icon as background image
CircleAvatar(
backgroundImage: _image != null
? AssetImage(_image.path)
: Icon(Icons.email), //<- here use icon as image
)
I know I can do something like this
CircleAvatar(
child: _image == null ? Icon(Icons.email) : null,
backgroundImage:
_image != null ? AssetImage(_image.path) : null,
)
I just found it a bit tedious adding 2 parameters for same purpose and also I want to use child parameter for something else