参数类型 'String?' 不能分配给参数类型"字符串",无论哪种方式都会触发 Dart 的空安全



在当前代码段中,我已将通知声明为可空,但对于if循环的通知,得到一个空安全错误。Body and notification.title.

下面是我的代码:

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
debugPrint('A new onMessageOpenedApp event was published!');
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)],
),
),
);
});
}
});

如果我将'notification'设置为非空,我将得到相同的空安全错误。

代码:

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
debugPrint('A new onMessageOpenedApp event was published!');
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)],
),
),
);
});
}
});

如何让这个工作?

感谢任何帮助!

编辑:将方法名称添加到编码部分。

这里发生了几件事。首先,您得到null错误的原因:

RemoteNotification? notification = message.notification;

notification是一个可空值时,当您尝试使用它而不首先检查它是否为空时,您将得到警告。将其更改为非空可以解决问题,但可能以一种您实际上不希望的方式。

现在当你把它改成non-nullable时,你没有改变它后面的行:

RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;

现在notification不再是空的,但你仍然使用空合并操作符创建android。这意味着,即使notification是非空的,android仍然是空的。由此,您将得到两个警告——一个是试图合并一个不可为空的值,另一个是使用android而不检查是否为空。

最简单的解决方案是使android也不可为空:

RemoteNotification notification = message.notification;
AndroidNotification android = message.notification.android;

但这可能不可能取决于message.notification本身是否可为空。


现在来看第二件事。假设我们希望notificationandroid为空,那么您的第一个空检查不足以消除showDialog回调中的警告。这是因为,即使知道在调用showDialog时,notification不为空,分析器也无法知道何时调用回调本身,到那时,notification可能已经变为空。由于这个原因,分析器别无选择,只能显示警告,而不管当前的空检查。

有四种方法可以解决这个问题。首先,您可以再次检查是否为空:

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

或者使用!运算符强制非空:

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

或者创建回调可以闭包的对象的非空版本:

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)],
),
),
);
},
);
}

我假设它的主体和标题可以为空。一种解决方案是在它们是空字符串的情况下回退到空字符串,如下所示:

return AlertDialog(
title: Text(notification.title ?? ''),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(notification.body ?? '')],
),
),
);

试试这个:

...
title: Text(notification.title as String),
...

相关内容

最新更新