how can sollve Problem related to null safety: A nullable expression can't be used as a condition - flutter

ChangeFavoritesModel? changeFavoritesModel;
void changeFavorites(int productId) {
favorites?[productId] = !favorites[productId];
DioHelper.postData(
url: FAVORITES,
data: {
'product_id': productId,
},
token: token,
).then((value) {
changeFavoritesModel = ChangeFavoritesModel.fromJson(value.data);
print(value.data);
emit(ShopSuccessChangeFavoritesState());
}).catchError((error) {
emit(ShopErrorChangeFavoritesState());
});
}
here,an error occurs:
favorites?[productId] = !favorites[productId];
and say:-
A nullable expression can't be used as a condition. (Documentation)
Try checking that the value isn't 'null' before using it as a condition.

because favorites is nullable, so check null first
if (favorites != null) {
favorites[productId] = !favorites[productId];
}
or if you could do an early return
if (favorites == null) {
return;
}

Related

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

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

How to fix a method/functionality in Flutter being executed so many times without loop?

I am working on a Flutter project which is a tricycle booking system that also uses Realtime Database in Firebase. If the ride status of the passenger has been accepted by the driver, an audio or notify sound will be executed then a modal popup/dialog will be displayed.
Upon trying, these two functionalities have been executed indefinitely and multiple times as long as the ride status of the passenger is accepted. How do I implement it once only and what is the reason behind it because I am not using any loop for this?
Here are the updated code for this method:
saveRideRequestInformation() //Ride Request Code
{
//1. save the Ride Request Information
referenceRideRequest = FirebaseDatabase.instance.ref().child("All Ride Requests").push(); // Creates unique ID
String? rideKey = referenceRideRequest!.key.toString();
var originLocation = Provider.of<AppInfo>(context, listen: false).userPickUpLocation;
var destinationLocation = Provider.of<AppInfo>(context, listen: false).userDropOffLocation;
Map originLocationMap =
{
//key:value
"latitude": originLocation!.locationLatitude.toString(),
"longitude": originLocation!.locationLongitude.toString(),
};
Map destinationLocationMap =
{
//key:value
"latitude": destinationLocation!.locationLatitude.toString(),
"longitude": destinationLocation!.locationLongitude.toString(),
};
Map userInformationMap =
{
"origin": originLocationMap,
"destination": destinationLocationMap,
"time": DateTime.now().toString(),
"username": userModelCurrentInfo!.username!,
"email": userModelCurrentInfo!.email!,
"id": userModelCurrentInfo!.id!,
"requestId": rideKey,
"originAddress": originLocation.locationName,
"destinationAddress": destinationLocation.locationName,
"driverId": "waiting",
"notified" : "false",
};
referenceRideRequest!.set(userInformationMap);
tripRideRequestInfoStreamSubscription = referenceRideRequest!.onValue.listen((eventSnap) async // getting updates in real time
{
if(eventSnap.snapshot.value == null)
{
return;
}
if ((eventSnap.snapshot.value as Map)["driverPlateNum"] != null) //!! GAWING CAR DETAILS/ PLATE NUMBER
{
setState(() {
driverTricDetails = (eventSnap.snapshot.value as Map)["driverPlateNum"].toString();
});
}
if ((eventSnap.snapshot.value as Map)["driverPhone"] != null) //!! GET PHONE NUMBER
{
setState(() {
driverPhone = (eventSnap.snapshot.value as Map)["driverPhone"].toString();
});
}
if ((eventSnap.snapshot.value as Map)["notified"] != null) //!! GET PHONE NUMBER
{
setState(() {
notified = (eventSnap.snapshot.value as Map)["notified"].toString();
});
}
if ((eventSnap.snapshot.value as Map)["driverName"] != null) //!! GET FNAME
{
setState(() {
driverName = (eventSnap.snapshot.value as Map)["driverName"].toString();
});
}
if((eventSnap.snapshot.value as Map)["status"] != null)
{
setState(() {
userRideRequestStatus = (eventSnap.snapshot.value as Map)["status"].toString();
});
}
if((eventSnap.snapshot.value as Map)["driverLocation"] != null)
{
double driverCurrentPositionLat = double.parse((eventSnap.snapshot.value as Map)["driverLocation"]["latitude"].toString());
double driverCurrentPositionLng = double.parse((eventSnap.snapshot.value as Map)["driverLocation"]["longitude"].toString());
LatLng driverCurrentPositionLatLng = LatLng(driverCurrentPositionLat, driverCurrentPositionLng);
if(userRideRequestStatus != null)
{
isVisible= !isVisible;
showUIForAssignedDriverInfo();
//when status = accepted
if(userRideRequestStatus == "accepted" && notified == "false") {
FirebaseDatabase.instance.ref()
.child("All Ride Requests")
.child(rideKey)
.child("notified")
.set("true");
passengerIsOfflineNow();
assignedDriverModal();
updateArrivalTimeToUserPickupLocation(driverCurrentPositionLatLng);
}
//when status = arrived
if(userRideRequestStatus == "arrived")
{
setState(() {
driverRideStatus = "Your driver has arrived.";
});
}
//when status = onTrip
if(userRideRequestStatus == "onTrip")
{
updateReachingTimeToUserDropOffLocation(driverCurrentPositionLatLng);
}
//when status = ended
if(userRideRequestStatus == "ended")
{
if((eventSnap.snapshot.value as Map)["fareAmount"] != null)
{
double fareAmount = double.parse((eventSnap.snapshot.value as Map)["fareAmount"].toString());
var response = await showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext c) => PayFareAmountDialog(
fareAmount: fareAmount,
),
);
if(response == "cashPayed")
{
//user can rate the driver
if((eventSnap.snapshot.value as Map)["driverId"] != null)
{
String assignedDriverId = (eventSnap.snapshot.value as Map)["driverId"].toString();
Navigator.push(context, MaterialPageRoute(builder: (c)=> RateDriverScreen(
assignedDriverId: assignedDriverId,
)));
referenceRideRequest!.onDisconnect();
tripRideRequestInfoStreamSubscription!.cancel();
}
}
}
}
}
}
});
onlineNearbyAvailableDriversList = GeoFireAssistant.activeNearbyAvailableDriversList;
//searchNearestOnlineDrivers();
}
Its because of the snapshot listener that runs when the driver location updates. As the driver location updates, it loops through everything in your if statement. This specifically:
if((eventSnap.snapshot.value as Map)["driverLocation"] != null)
{
double driverCurrentPositionLat = double.parse((eventSnap.snapshot.value as Map)["driverLocation"]["latitude"].toString());
double driverCurrentPositionLng = double.parse((eventSnap.snapshot.value as Map)["driverLocation"]["longitude"].toString());
LatLng driverCurrentPositionLatLng = LatLng(driverCurrentPositionLat, driverCurrentPositionLng);
if(userRideRequestStatus != null)
{
isVisible= !isVisible;
showUIForAssignedDriverInfo();
//when status = accepted. !! this is my concern !!
if(userRideRequestStatus == "accepted")
...
What you could consider doing is adding a flag in the eventSnap.snapshot.value to say something along the lines of notified. And then after you run the if(userRideRequestStatus == "accepted") statement, flip the notified value to true. This would then change your accepted if statement from if(userRideRequestStatus == "accepted") to if(userRideRequestStatus == "accepted" && !driverNotified).

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

The function call is not returning null but still giving "null" to be returned error

I'm migrating my old version flutter code to latest version with null safety feature.
In a function call I am getting the error "The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type". I have enclosed my code in try catch block and in catch block I added rethrow statement to prevent null exception.
This is my code.
Future<Map<String, dynamic>> fetchTimeline(http.Client client) async {
try {
print('INVOICE URL: ${globals.ursl.getURL(URLS.GETINVOICEURL)}');
Response response;
Dio dio = new Dio();
response = await dio.get(globals.ursl.getURL(URLS.GETINVOICEURL));
print('INVOICE GET RESPONSE: $response');
if (response.statusCode == 200) {
Map mapobject = (json.decode(response.toString()));
var succes = mapobject['success'];
if (succes == 1) {
if (mapobject['Invoice'][0]['address'] == null ||
mapobject['Invoice'][0]['address'] == '') {
address = '';
} else {
address = mapobject['Invoice'][0]['address'];
}
if (mapobject['Invoice'][0]['contact'] == null ||
mapobject['Invoice'][0]['contact'] == '')
phone = '';
else
phone = mapobject['Invoice'][0]['contact'];
if (mapobject['Invoice'][0]['restaurant_name'] == null ||
mapobject['Invoice'][0]['restaurant_name'] == '') {
name = ' ';
} else {
name = mapobject['Invoice'][0]['restaurant_name'];
}
logo = mapobject['Invoice'][0]['logo'];
globals.invoiceData = mapobject['Invoice'][0];
startTime();
return mapobject['Invoice'][0];
} else {
return {};
}
}
} catch (error) {
client.close();
print("CONNECTION CLOSED: $error");
rethrow;
}
}
I have added rethrow in catch block but still error is there.
Anyone there to help me out.
Thanks
It's a little hard to see with all the nested if statements, but you aren't returning a Map<String, dynamic> in every branch. This condition if (response.statusCode == 200) { ... } does not have a corresponding else branch, and so if the statusCode is some value other than 200 you are not returning anything (which means you are implicitly returning null in that case).

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