In this current snippet I have declared notification to be nullable but get an null safe error for the if loop's notification.body and notification.title.
Here's my code:
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text(notification.title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(notification.body)],
),
),
);
});
If I make 'notification' to be non nullable, I get the same null safe error.
Code:
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null && android != null) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text(notification.title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(notification.body)],
),
),
);
});
How to get this to work?
Any help appreciated!
CodePudding user response:
I'm assuming it's body and title that could be null. A solution is to fallback to empty strings in case they are, like this:
return AlertDialog(
title: Text(notification.title ?? ''),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(notification.body ?? '')],
),
),
);
CodePudding user response:
A couple things going on here. First, the reason you are getting the null error:
RemoteNotification? notification = message.notification;
When notification
is a nullable value, you will get the warning when you attempt to use it without first checking if it is null. Changing it to be non-nullable can resolve the problem, but potentially in a way you don't actually want.
Now when you changed it to non-nullable, you didn't change the line after it:
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
Now notification
is no longer nullable, but you still use a null-coalescing operator when creating android
. That means that, even though notification
is non-nullable, android
still is nullable. From this, you will get two warnings - one for trying to coalesce a non-nullable value, and one for using android
without checking for null.
The easiest solution would be to make it so android
is non-nullable as well:
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification.android;
But this might not be possible depending on whether message.notification
itself is nullable.
Now onto the second thing. Assuming we want notification
and android
to be nullable, your first null-check isn't enough to eliminate the warning within the callback to showDialog
. This is because, even though it is known that when showDialog
is called, notification
is not null, the analyzer can't know when the callback itself will be called, and by that point, notification
might have become null. For that reason, the analyzer has no choice but to display the warning regardless of your current null check.
There are four ways to resolve this. First, you could check for null again:
if (notification != null && android != null) {
showDialog(
context: context,
builder: (_) {
if (notification != null && android != null) {
return AlertDialog(
title: Text(notification.title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(notification.body)],
),
),
);
} else {
// Return a different widget if null check fails
}
},
);
}
Or force non-null with the !
operator:
if (notification != null && android != null) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text(notification!.title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(notification!.body)],
),
),
);
},
);
}
Or provide default values in the case that the objects are null:
if (notification != null && android != null) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text(notification?.title ?? 'Default Value'),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(notification?.body ?? 'Default Value')],
),
),
);
},
);
}
Or make non-null versions of the objects that the callback can closure around:
if (notification != null && android != null) {
final notificationNN = notification;
final androidNN = android;
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text(notificationNN.title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(androidNN.body)],
),
),
);
},
);
}
CodePudding user response:
Try this:
...
title: Text(notification.title as String),
...