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

I'm trying to handle some data for a flutter application, however I am getting the following error on my code:
The method 'add' 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 ('!').
Map<String, List<SourcefulListing>> sortedSkills = {};
QuerySnapshot listingSnapshot = await listingsRef.get();
List<SourcefulListing> listings = [];
for (int i = 0; i < listingSnapshot.docs.length; i++) {
listings.add(SourcefulListing.fromJson(
listingSnapshot.docs[i].data() as Map<String, dynamic>));
}
for (String skill in skills) {
for (SourcefulListing listing in listings) {
if (listing.selectedSkill == skill) {
if (sortedSkills[skill] == null || sortedSkills[skill] != []) {
sortedSkills[skill] = [listing];
} else {
sortedSkills[skill] = sortedSkills[skill].add(listing);
}
}
}
}
Basically I have a Map with Strings as key and List for the values. The for each loop should add the SourcefulListing object to the map, however there is an error on the .add method.
Any help would be much appreciated.

Try this,
Map<String, List<SourcefulListing>> sortedSkills = {};
QuerySnapshot listingSnapshot = await listingsRef.get();
List<SourcefulListing> listings = [];
for (int i = 0; i < listingSnapshot.docs.length; i++) {
listings.add(SourcefulListing.fromJson(
listingSnapshot.docs[i].data() as Map<String, dynamic>));
}
for (String skill in skills) {
for (SourcefulListing listing in listings) {
if (listing.selectedSkill == skill) {
if (sortedSkills[skill] == null || sortedSkills[skill] != []) {
sortedSkills[skill] = [listing];
} else {
sortedSkills[skill]?.add(listing); // changes made here
setState(() {}); // update ui
}
}
}
}
Null Safety : https://dart.dev/null-safety

Related

how to filter data from stream builder in flutter

body: Observer<List<CompleteInventroyModel>>(
stream:call? completeInventoryManager.mainList:Stream.empty(),
onSuccess: (context, snapshot) {
List<CompleteInventroyModel> screendata =List.from(snapshot) ;
// List showlist=screendata[0].data.where((item) => item.areaId==1) as List;
//
if(filterData == true){
** showlist = screendata.map((e) => e).toList();
print("===========snapshot length============${snapshot[0].data.length}");
print("===========showlist[0].data.length============${showlist[0].data.length}");
print("===========screendata[0].data.length============${screendata[0].data.length}");
for (int i = 0; i < screendata[0].data.length; i++) {
print("==============i============${i}");
print('area_dv ${area_dv}');
// modeldata.Data obj = screendata[0].data[i];
if (screendata[0].data[i].area.name != area_dv) {
showlist[0].data.removeAt(i);
// showlist[0].data.add(screendata[0].data[i]);
//break;
// print("=================obj daata ${obj.area.name}");
}
}**
}
else if(filterData == false){
showlist = screendata.map((e) => e).toList();
}
I have tried both add and removeAt() method in remove add method also remove data from model original list and in add() method loop can't break ..any solution??

Listen to a new value of a bloc and generate a list of listened items

I have this StreamSubscription field called followSubscribtion. It listens if there is a new follower and then calls populateFollower to load follower profile.
followsSubscription =
getBloc(context).followsHandler.stream.listen((value) async {
if (value.status == Status.success) {
await populateFollows();
}
});
});
populateFollows() async{
if (getBloc(context).followsModel.length > 0) {
for (var i = 0; i < getBloc(context).followsModel.length; i++) {
getBloc(context).loadFollowsProfile(getBloc(context).followsModel[i].userId);
break;
}
}
}
This works fine, But I want each profile that will be loaded to be added to a list, How do I do that?
loadFollowsProfile method
loadFollowsProfile(int id , List<UserProfileModel> profileList) {
getFollowsProfileHandler.addNetworkTransformerStream(
Network.getInstance().getUserProfile(id), (_) {
userProfileModelBloc = UserProfileModel.fromJson(_);
profileList.add(userProfileModelBloc);
return userProfileModelBloc;
});
}
You can do this by setting up loadFollowsProfile() to return a UserProfileModel, adding that to a list in the for loop of populateFollows(), and then returning that list from populateFollows().
List<ProfileObject> populateFollows() async{
List<ProfileObject> profileList = [];
if (getBloc(context).followsModel.length > 0) {
for (var i = 0; i < getBloc(context).followsModel.length; i++){
profileList.add(getBloc(context).loadFollowsProfile(
getBloc(context).followsModel[i].userId
));
break;
}
}
return profileList;
}
followsSubscription =
getBloc(context).followsHandler.stream.listen((value) async {
if (value.status == Status.success) {
profileList = await populateFollows();
}
});
});

Don't execute assignment if value is null

I am still coming up to speed with dart and wanted to know if there was an easier way to not execute a statement if the value is null. See example below:
I can always do the if statements below for setting field3 and field4, but felt like something like field5 should work. But when I try to do that, it complains that a null check operator is used on a null value.
Also I don't want to change the Map to have a dynamic value.
Is there a single one liner to do what I am trying to do, or do I just need to check for null before setting the value.
Map<String, Object> myMap = {};
print('running now');
try {
myMap['field1'] = DummyClass.getString('hello');
myMap['field2'] = DummyClass.getString('good');
//Is there a more concise way to do this than the 2 options below?
if (DummyClass.getOptionalString('goodbye') != null) {
myMap['field3'] = DummyClass.getOptionalString('goodbye')!;
}
String? temp = DummyClass.getOptionalString('go');
if (temp != null) {
myMap['field4'] = temp;
}
// This gives an error 'null check operator used on a null value'
// myMap['field5'] ??= DummyClass.getOptionalString('to')!;
} catch (e) {
print('error condition, $e');
}
print(myMap);
}
class DummyClass {
static String getString(String? strParam) {
String? retString = getOptionalString(strParam);
if (retString == null) {
throw ('nulls are not allowed');
}
return retString;
}
static String? getOptionalString(String? strParam) {
if (strParam == null || strParam.length < 3) {
return null;
}
return strParam;
}
}
There's no built-in way to do what you want, but you could write a function (or extension method) to do it. For example:
extension MapTrySet<K, V> on Map<K, V> {
void trySet(K key, V? value) {
if (value != null) {
this[key] = value;
}
}
}
and then you could do:
myMap.trySet('field3', DummyClass.getOptionalString('goodbye'));
myMap.trySet('field4', DummyClass.getOptionalString('go'));
Alternatively, if you really want to use normal Map syntax, you could create your own Map class that has a void operator []=(K key, V? value) override and does nothing when the value is null, but that probably would not be worth the effort.
The issue is that the ??= operator assigns to the left if it is null. Expanded, it would look something like this:
a ??= b;
// Equivalent to:
if (a == null) {
a = b;
}
Which is not something that you're trying to achieve. AFAIK, there is no such operator yet in Dart. However, you can try this:
final possiblyNullValue = '';
final myMap = <String, String>{};
myMap['key'] = possiblyNullValue ?? myMap['key'];
// Equivalent to:
if (possiblyNullValue != null) {
myMap['key'] = possiblyNullValue;
}
// or:
myMap['key'] = possiblyNullValue != null? possiblyNullValue : myMap['key'];
Which would work in your case as a one-liner.
You could create your map with all entries, even null, and then filter the null values out:
void main() {
try {
final myMap = <String, dynamic>{
'field1': DummyClass.getString('hello'),
'field2': DummyClass.getString('good'),
'field3': DummyClass.getOptionalString('goodbye'),
'field4': DummyClass.getOptionalString('go'),
}..removeWhere((k, v) => v == null);
print(myMap);
} catch (e) {
print('error condition, $e');
}
}

Fixed List is not updating with for loop - Flutter

I've a fixed list reservedGuest. After checking the condition in for loop I want to update the seats if the membership date has expired. The list is not updating. The code is as follows. PS. The List is filled through API on init().
class MyClubController extends GetxController {
List goldLane = List.filled(3, null, growable: false);
void _alterLanesOnContractEnds() {
for (var i in goldLane) {
print("\n\n I: $i");
if (i == null ||
DateTime.parse(i['contractEnds']).isBefore(
DateTime.now(),
)) {
i = null;
print('Can be removed');
} else {
print('Cannot be removed');
}
}
update();
}
}
A for-in loop will not allow you to reassign elements of the List. When you do:
for (var i in goldLane) {
// ...
i = null;
}
you are reassigning what the local i variable refers to, not mutating the goldLane List.
You instead can iterate with an index:
void _alterLanesOnContractEnds() {
for (var i = 0; i < goldLane.length; i += 1) {
var element = goldLane[i];
print("\n\n I: $element");
if (element == null ||
DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)) {
goldLane[i] = null;
print('Can be removed');
} else {
print('Cannot be removed');
}
}
update();
}
You can just create a new List where unqualified guests are nullified. For example,
void _alterLanesOnContractEnds() {
goldLane = goldLane.map(
(guest) => guest == null || DateTime.parse(guest['contractEnds']).isBefore(DateTime.now()) ? null: guest
).toList(growable: false);
update();
}
You should not and cannot modify a list while iterating with its iterator.
Elaborated by Jamesdlin,
Modifying the elements of a List while iterating is fine. Modifying
the length of the List while iterating is not, but that won't be a
problem for a non-growable List.
The bottom line is you should not mutate the size of the list while iterating.
I solved it by using
goldLane.forEach(
(element) {
print('\n\n ELEMENT: $element');
if (element == null ||
DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)) {
int ix = goldLane.indexWhere(
(element) => element != null
? DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)
: true,
);
goldLane[ix] = null;
} else {
print('Cannot be removed');
}
},
);
Yet I'll test the other answers. Thank You.

Flutter : Conditions must have a static type of 'bool'

I'm trying to learn firebase with flutter and i ran into this problem
here is my code :
FirebaseFirestore.instance
.collection('attendees')
.doc(user.uid)
.snapshots()
.listen((snapshot) {
if (snapshot.data() != null) {
if (snapshot.data()!['attending']) {
_attending = Attending.yes;
} else {
_attending = Attending.no;
}
} else {
_attending = Attending.unknown;
}
notifyListeners();
});
what is the solution ?
the exact problem is within this line :
if (snapshot.data()!['attending']) {
how can I rewrite this so i wont ruin the current functionality ?
I appreciate your help inadvance
The reason you are getting error -
Conditions must have a static type of 'bool'
because on line snapshot.data()!['attending'] an = sign is missing.
To make your code work just do
if (snapshot.data() != snapshot.data()!['attending']) {
_attending = Attending.yes;
} else {
_attending = Attending.no;
}
Understanding The Error
I would also like to point out that Dart a stricter language (more like Java in terms of 'truthy' values).
In JavaScript you can use any ‘truthy’ value in a conditional statement. In Dart you cannot use ‘truthy’ values. For example:
var name = 'Joe';
if (name) {
// do something...
OR
var a = 1
if(a){
//this would work in JavaScript
}
You cannot do such things in Java or Dart. The reason is that Dart requires that a condition is a bool true not just a 'truthy' value. You could correct the code by changing it to:
if (name.isNotEmpty)
OR
if(a==1)
{
//these == signs are really important
}
Just store the snapshot.data() to the local map variable and do the operations by that.
_attendingSubscription = FirebaseFirestore.instance
.collection('attendees')
.doc(user.uid)
.snapshots()
.listen((snapshot) {
final Map<String, dynamic>? data = snapshot.data();
if (data != null) {
_attending = data['attending'] ? Attending.yes : Attending.no;
} else {
_attending = Attending.unknown;
}
notifyListeners();
});