这是我的聊天屏幕代码
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
''
键入后,当我点击发送图标时,我会收到这样的错误:
"════════手势捕捉到异常═══════════════════════════════════════════空值上使用的空检查运算符
════════════════════════════════════════════════════════════════════════
"有人能帮助解决这个问题吗
深入研究您的代码后,我可以看到这个函数从未被称为
doThisOnlaunch() async {
await getMyInfoFromSharedPreference();
}
因此getMyInfoFromSharedPreference()
函数从未被调用所以chatRoomId
没有初始化,它将始终为空。因为这个代码
String? chatRoomId, messageId = "";
在这个方法中,您使用的是chatRoomId
上的!
,它为null。
DatabaseMethods()
.addMessage(chatRoomId!, messageId!, messageInfoMap).then((value) {...
这就是导致错误的原因。
解决方案
在类似initState
的上调用tis方法
String? chatRoomId, messageId = "";
String? myName, myProfilePic, myUserName, myEmail;
TextEditingController messageEditingController = TextEditingController();
@override
void initState() {
super.initState();
doThisOnlaunch();
}
.
.
.
或者只是用一个值初始化chatRoomId
,并将其声明为不可为null的字符串
String chatRoomId="", messageId = "";
请注意,第二个解决方案只会停止错误,但您的代码将无法正常运行
您在某个变量上使用了!
,而该变量为null。检查错误所在位置。
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";
}}
如果函数依赖于此,为什么允许可以为null的变量?
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";
}
}