空值检查运算符不能用于空值
Posted
技术标签:
【中文标题】空值检查运算符不能用于空值【英文标题】:Null check operator cannot used on null value 【发布时间】:2021-11-03 19:47:33 【问题描述】:这是我的聊天屏幕代码
import 'package:flutter/material.dart';
import 'package:messenger/helperfunction/sharedpref_helper.dart';
import 'package:messenger/services/database.dart';
import 'package:random_string/random_string.dart';
class ChatScreen extends StatefulWidget
final String chatWithusername, name;
ChatScreen(this.chatWithusername, this.name);
@override
_ChatScreenState createState() => _ChatScreenState();
class _ChatScreenState extends State<ChatScreen>
String? chatRoomId, messageId = "";
String? myName, myProfilePic, myUserName, myEmail;
TextEditingController messageEditingController = TextEditingController();
getMyInfoFromSharedPreference() async
myName = await SharedPreferenceHelper().getDisplayName();
myProfilePic = await SharedPreferenceHelper().getUserProfileUrl();
myUserName = await SharedPreferenceHelper().getUserName();
myEmail = await SharedPreferenceHelper().getUserEmail();
chatRoomId = getChatRoomIdByUsername(widget.chatWithusername, myUserName);
getChatRoomIdByUsername(String? a, String? b)
if (a!.substring(0, 1).codeUnitAt(0) > b!.substring(0, 1).codeUnitAt(0))
return "$b\_$a";
else
return "$a\_$b";
addMessage(bool sentClicked)
if (messageEditingController.text != "")
String message = messageEditingController.text;
var lastMessageTs = DateTime.now();
Map<String, dynamic> messageInfoMap =
"message": message,
"sentBy": myUserName,
'ts': lastMessageTs,
"imgUrl": myProfilePic
;
//Gentrate the message id
if (messageId == "")
messageId = randomAlphaNumeric(12);
DatabaseMethods()
.addMessage(chatRoomId!, messageId!, messageInfoMap)
.then((value)
Map<String, dynamic>? lastMessageInfoMap =
"lastmessage": message,
"lastMessageSendTs": lastMessageTs,
"lastMessageSendBy": myUserName
;
DatabaseMethods()
.updateLastmessageSend(chatRoomId!, lastMessageInfoMap);
if (sentClicked)
messageEditingController.text = "";
messageId = "";
);
getAnfSentMessages() async
doThisOnlaunch() async
await getMyInfoFromSharedPreference();
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text(widget.name),
),
body: Container(
child: Stack(
children: [
Container(
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.black.withOpacity(0.8),
padding: EdgeInsets.symmetric(
horizontal: 6,
vertical: 8,
),
child: Row(
children: [
Expanded(
child: TextField(
controller: messageEditingController,
onChanged: (value)
addMessage(false);
,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
hintText: " Type a message",
hintStyle: TextStyle(
color: Colors.white.withOpacity(0.6))),
),
),
GestureDetector(
onTap: ()
addMessage(true);
,
child: Icon(Icons.send, color: Colors.white))
],
),
),
)
],
),
),
);
这是我的数据库;
import 'package:cloud_firestore/cloud_firestore.dart';
// ignore: unused_import
import 'package:firebase_core/firebase_core.dart';
class DatabaseMethods
Future addUserInfoToDB(
String userId, Map<String, dynamic> userInfoMap) async
return FirebaseFirestore.instance
.collection("users")
.doc(userId)
.set(userInfoMap);
Future<Stream<QuerySnapshot>> getUserByUserName(String username) async
return FirebaseFirestore.instance
.collection("users")
.where("username", isEqualTo: username)
.snapshots();
Future addMessage(String chatRoomId, String messageId,
Map<String, dynamic> messageInfoMap) async
return FirebaseFirestore.instance
.collection("chatRooms")
.doc(chatRoomId)
.collection("chats")
.doc(messageId)
.set(messageInfoMap);
updateLastmessageSend(
String chatRoomId, Map<String, dynamic> lastMessageInfoMap)
return FirebaseFirestore.instance
.collection("chatRooms")
.doc(chatRoomId)
.update(lastMessageInfoMap);
createChatRoom(
String chatRoomId, Map<String, dynamic> chatRoomInfoMap) async
final snapShot = await FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.get();
if (snapShot.exists)
//chatroom already exits
return true;
else
//chatRoom does not exit:
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.set(chatRoomInfoMap);
当我运行此代码并开始在 textformfield 中输入时,我收到以下错误: '''
════════ Exception caught by widgets
═══════════════════════════════════════════
The following _CastError was thrown while calling onChanged:
Null check operator used on a null value
When the exception was thrown, this was the stack
#0 _ChatScreenState.addMessage
package:messenger/view/chatscreen.dart:54
#1 _ChatScreenState.build.<anonymous closure>
package:messenger/view/chatscreen.dart:103
#2 EditableTextState._formatAndSetValue
package:flutter/…/widgets/editable_text.dart:2298
#3 EditableTextState.updateEditingValue
package:flutter/…/widgets/editable_text.dart:1749
#4 TextInput._handleTextInputInvocation
package:flutter/…/services/text_input.dart:1351
'''
输入后,当我点击发送图标时,出现如下错误:
''' ════════ 手势捕获的异常 ═════════════════════════════════════════╕ 用于空值的空检查运算符
════════════════════════════════════════════════════════════════════════
''' 谁能帮忙解决这个问题
【问题讨论】:
我看到的唯一null
检查是在chatRoomId!, messageId!
上完成的,其中一个值是null
。
【参考方案1】:
深入研究您的代码后,我可以看到从未调用过此函数
doThisOnlaunch() async
await getMyInfoFromSharedPreference();
所以getMyInfoFromSharedPreference()
函数永远不会被调用
所以chatRoomId
没有被初始化,它永远是 null 因为这段代码
String? chatRoomId, messageId = "";
在这种方法中,您在chatRoomId
上使用!
,它是空的。
DatabaseMethods()
.addMessage(chatRoomId!, messageId!, messageInfoMap).then((value) ...
所以这就是导致错误的原因。
解决方案
在initState
like 上调用 tis 方法
String? chatRoomId, messageId = "";
String? myName, myProfilePic, myUserName, myEmail;
TextEditingController messageEditingController = TextEditingController();
@override
void initState()
super.initState();
doThisOnlaunch();
.
.
.
或者只是用一个值启动chatRoomId
并将它们声明为不可为空的字符串
String chatRoomId="", messageId = "";
请注意,第二个解决方案只会停止错误,但您的代码将无法正常运行
【讨论】:
感谢您的帮助,还需要添加 "late String chatRoomId, messageId = "";" 不客气。添加late意味着这些字段不可为空,但会在应用的后期初始化,所以使用时要小心。【参考方案2】:getChatRoomIdByUsername(String? a, String? b)
if (a!.substring(0, 1).codeUnitAt(0) > b!.substring(0, 1).codeUnitAt(0))
return "$b\_$a";
else
return "$a\_$b";
如果函数依赖于此,为什么要允许可空变量?
getChatRoomIdByUsername(required String a,required String b)
if (a.substring(0, 1).codeUnitAt(0) > b.substring(0, 1).codeUnitAt(0))
return "$b\_$a";
else
return "$a\_$b";
【讨论】:
如果我更改所需的字符串,则会显示错误:此处不能有修饰符“必需”。尝试删除“必需”。getChatRoomIdByUsername(required String a,required String b)
检查您的代码是否缺少大括号
【参考方案3】:
您在某个变量上使用了!
,而该变量为空。检查错误所在。
【讨论】:
我不知道如何找到它。我对扑腾完全陌生。你能帮忙解决这个错误吗以上是关于空值检查运算符不能用于空值的主要内容,如果未能解决你的问题,请参考以下文章
Flutter Bloc Test:空值检查运算符用于空值(空安全)
Firebase.initializeApp() 给出错误:空值检查运算符用于空值
SharedPreferences.getInstance() 正在抛出 _CastError(空值检查运算符用于空值)