How to avoid [] called on null in Flutter - dart

Is there is a method in dart to judge whether an object is null or not, and then decide to get ['data'] or do nothing?
This is the error message:
The following NoSuchMethodError was thrown building Builder:
The method '[]' was called on null.
Receiver: null
Tried calling:

The simplest way to answer your question:
final data = list != null ? list[0] : null;
There is a shorthand method to do the same with properties and methods of any object : a?.b or a?.b() would first null check a and then get b or call b respectively, if a is null return null.
Such shorthand is not available for subscript only for properties and methods.

Prefer Null aware index operator:
var item = yourList?[0] ?? defaultValue;

Related

Dart null safety conditional statement?

So I have a class Cache which has a method compare that returns a bool.
I have an instance of this class that is nullable.
Cache? recent;
I want to executed a piece of code when recent is not null and compare returns false
Without null safety I would have just done
if(recent!=null && !recent.compare()){
//code
}
How to do the same with null safety enabled?
When I try above with null safety I get
The method 'compare' 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 ('!')
When I try below
if(!recent?.compare()){
//code
}
It gives me
A nullable expression can't be used as a condition.
Try checking that the value isn't 'null' before using it as a condition.
You can solve this problem either by
Using local variable (recommended)
var r = recent; // Local variable
if (r != null && !r.compare()) {
// ...
}
Using Bang operator (!)
if (!recent!.compare()) {
// ...
}

How to add item to list with Null Safety

I have problem working with null safety in dart.
void main() {
List<String>? testlist;
testlist?.add('null test');
print(testlist);
}
Why the printed testlist is still null?
Your testlist is still null, because you defined it as nullable and did not initialize it.
So when it comes to adding an entry to your testlist, while calling testlist?.add('null test');. A check will be performed, if testlist is null. If it is null, the call for add will be skipped. And in your case, it is always null.
So to visualize the null-conditional operator in your code line testlist?.add('null test');. It could also be written as:
List<String>? testlist;
// testlist?.add('null test');
if(testlist != null) {
testlist.add('null test');
}
print(testlist);
If you want to add the string, you have to initialize your testlist:
List<String>? testlist = [];
Or if possible you could avoid the nullable and write your code as:
List<String> testlist = [];
testlist.add('null test');
print(testlist);
Because you haven't assigned a value to testlist, it's null and the add method is not executed.
The add method simply "adds" an entry to the list, but if the list is null you can't add anything to it.
You have to initialize it somehow, for example as List<String>? testlist = [];, but it depends how you'll use it in the end.

Should a field be left null or initialized to a default value when fetching data from an API in null safe Dart?

Should I set a value to every null fields when retrieving something something from an api? Or should I keep them null and check when displaying them if they aren't null?
Ex:
factory Geo.fromJson(Map<String, dynamic> json) => Geo(
type: json["type"] == null ? 'Point' : json["type"],
coordinates: json["coordinates"] == null ? [] : List<double>.from(json["coordinates"].map((x) => double.tryParse(x))),
);
or
factory Geo.fromJson(Map<String, dynamic> json) => Geo(
type: json["type"] == null ? null : json["type"],
coordinates: json["coordinates"] == null ? null : List<double>.from(json["coordinates"].map((x) => double.tryParse(x))),
);
Edit --> or should I be doing this in an other way like this maybe?
factory Location.fromJson(Map<String, dynamic> json) {
return Location(
geo: json["geo"] = Geo.fromJson(json["geo"]),
city: json["city"] = json["city"],
country: json["country"] = json["country"],
area: json["area"] = json["area"],
);
}
null-safety in Dart is not a campaign to get rid of null. null is a valid information.
Take the easiest example: does my wife want a pizza? Seems like an easy true/false question. Until you consider that "I haven't asked her yet" is indeed a real world state that is just as valid.
So no, you should not replace all your null values with something else. You would lose information.
So again: null safety does not mean you get rid of the null value. It means you no longer get surprised by the null value.
If you have values that can legitimately be null, then let them be.
You got improved compiler support now to make sure you don't drop the ball and mistakenly assume they are always non-null. That's great. Be happy about it.

Searching a List of objects for a particular object in dart using "where"

I would like to obtain an object from a List based on a specific search criteria of its member variable
this is the code I am using
class foo
{
foo(this._a);
int _a;
}
List<foo> lst = new List<foo>();
main()
{
foo f = new foo(12);
lst.add(f);
List<foo> result = lst.where( (foo m) {
return m._a == 12;
});
print(result[0]._a);
}
I am getting the error and not sure how to resolve this
Uncaught exception:
TypeError: Instance of 'WhereIterable<foo>': type 'WhereIterable<foo>' is not a subtype of type 'List<foo>'
I am trying to search for an object whose member variable a == 12. Any suggestions on what I might be doing wrong ?
The Iterable.where method returns an iterable of all the members which satisfy your test, not just one, and it's a lazily computed iterable, not a list. You can use lst.where(test).toList() to create a list, but that's overkill if you only need the first element.
You can use lst.firstWhere(test) instead to only return the first element, or you can use lst.where(test).first to do effectively the same thing.
In either case, the code will throw if there is no element matched by the test.
To avoid throwing, you can use var result = lst.firstWhere(test, orElse: () => null) so you get null if there is no such element.
Another alternative is
foo result;
int index = lst.indexWhere(test);
if (index >= 0) result = lst[index];
The answer is simple. Iterable.where returns an Iterable, not a List. AFAIK this is because _WhereIterable does its computations lazily.
If you really need to return a List, call lst.where(...).toList().
Otherwise, you can set result to be an Iterable<foo>, instead of a List<foo>.
or you can go crazy and do this:
bool checkIfProductNotFound(Map<String, Object> trendingProduct) {
bool isNotFound = this
._MyProductList
.where((element) => element["id"] == trendingProduct["id"])
.toList()
.isEmpty;
return isNotFound ;
}

Method doesn't work when I use ? after int

I have this Action method :
public ActionResult Index(int? mid)
{
IList<SubGroup> SubGroupLit = (mid != null) ? _subGroupService.GetAllWithGroupId(mid) : _subGroupService.GetAll();
return View(SubGroupLit);
}
I getting this ERROR:
he best overloaded method match for 'ServiceLayer.Interfaces.ISubGroupService.GetAllWithGroupId(int)' has some invalid arguments
But when I remove the ? after the int (in Index parameters), it works fine .
What is wrong?
The ? means it's nullable. Your GetAllWithGroupId method, however, only accepts int. If mid just happens to come through as null, then it can't be passed into that method because null is not an int. Hence the error. What you'll have to do is make mid just an int, which, as you noted already, works. Or you'll need to check mid has a value and then pass the value into the method. It looks like you were already attempting to do this with the ternary, but you made a few mistakes. The following code should work:
IList<SubGroup> SubGroupLit = mid.HasValue ? _subGroupService.GetAllWithGroupId(mid.Value) : _subGroupService.GetAll();

Resources