Dart使用xmpp_stone插件时如何修复空检查报错问题
Dart xmpp_stone插件空检查报错修复
- 开发语言:Dart
- 问题描述:使用xmpp_stone插件开发XMPP通信功能时触发空检查报错,无法独立完成修复
- 报错截图:

问题关联原始代码
import 'dart:io'; import 'package:xmpp_stone/src/logger/Log.dart'; import 'package:console/console.dart'; import 'dart:async'; import 'dart:convert'; import 'package:xmpp_stone/xmpp_stone.dart' as xmpp; import 'package:image/image.dart' as image; final String TAG = 'example'; class ExampleConnectionStateChangedListener implements xmpp.ConnectionStateChangedListener { late xmpp.Connection _connection; late xmpp.MessagesListener _messagesListener; StreamSubscription<String>? subscription; ExampleConnectionStateChangedListener(xmpp.Connection connection, xmpp.MessagesListener messagesListener) { _connection = connection; _messagesListener = messagesListener; _connection.connectionStateStream.listen(onConnectionStateChanged); } @override void onConnectionStateChanged(xmpp.XmppConnectionState state) { if (state == xmpp.XmppConnectionState.Ready) { Log.d(TAG, 'Connected'); _connection.getMamModule().queryAll(); var vCardManager = xmpp.VCardManager(_connection); vCardManager.getSelfVCard().then((vCard) { if (vCard != null) { Log.d(TAG, 'Your info' + vCard.buildXmlString()); } }); var messageHandler = xmpp.MessageHandler.getInstance(_connection); var rosterManager = xmpp.RosterManager.getInstance(_connection); messageHandler.messagesStream.listen(_messagesListener.onNewMessage); sleep(const Duration(seconds: 1)); var receiver = 'yyy@gmail.com'; var receiverJid = xmpp.Jid.fromFullJid(receiver); rosterManager.addRosterItem(xmpp.Buddy(receiverJid)).then((result) { if (result.description != null) { print("TAG, 'add roster'" + result.description!); } }); sleep(const Duration(seconds: 1)); vCardManager.getVCardFor(receiverJid).then((vCard) { if (vCard != null) { print("TAG, 'Receiver info'" + vCard.buildXmlString()); if (vCard != null && vCard.image != null) { var file = File('test456789.jpg')..writeAsBytesSync(image.encodeJpg(vCard.image!)); print("TAG, IMAGE SAVED TO: ${file.path}"); } } }); var presenceManager = xmpp.PresenceManager.getInstance(_connection); presenceManager.presenceStream.listen(onPresence); } } void onPresence(xmpp.PresenceData event) { Log.d(TAG, 'presence Event from ' + event.jid!.fullJid! + ' PRESENCE: ' + event.showElement.toString()); } } Stream<String> getConsoleStream() { return Console.adapter.byteStream().map((bytes) { var str = ascii.decode(bytes); str = str.substring(0, str.length - 1); return str; }); } class ExampleMessagesListener implements xmpp.MessagesListener { @override void onNewMessage(xmpp.MessageStanza? message) { if (message!.body != null) { Log.d(TAG ,format( 'New Message from {color.blue}${message.fromJid!.userAtDomain}{color.end} message: {color.red}${message.body}{color.end}')); } } @override void onChatMessage(xmpp.MessageStanza? message) { print(message); if (message!.body != null) { Log.d(TAG,format( 'New Message from {color.blue}${message.fromJid!.userAtDomain}{color.end} message: {color.red}${message.body}{color.end}')); } } } sendmessageforxmpp(){ var userAtDomain = 'xxx@gmail.com'; var password = 'password'; var jid = xmpp.Jid.fromFullJid(userAtDomain); var account = xmpp.XmppAccountSettings(userAtDomain, jid.local, jid.domain, password, 5222, resource: 'xmppstone'); var connection = xmpp.Connection(account); var receiver = 'yyy@gmail.com'; var receiverJid = xmpp.Jid.fromFullJid(receiver); Log.d(TAG, receiverJid.fullJid.toString()); var messageHandler = xmpp.MessageHandler.getInstance(connection); messageHandler.sendMessage(receiverJid, "str"); }
报错根因与修复方案
所有空检查报错均来自Dart空安全机制下的不规范写法、逻辑时序错误,按以下点逐一修改即可解决:
- 修正消息监听的强制非空断言滥用问题
原代码在onNewMessage、onChatMessage方法中直接对可空参数message使用!强制非空,一旦流中传入null值会直接触发空异常。替换为正常判空逻辑,同时去掉fromJid的强制非空断言:
@override void onNewMessage(xmpp.MessageStanza? message) { if (message != null && message.body != null) { Log.d(TAG ,format( 'New Message from {color.blue}${message.fromJid?.userAtDomain}{color.end} message: {color.red}${message.body}{color.end}')); } } @override void onChatMessage(xmpp.MessageStanza? message) { print(message); if (message != null && message.body != null) { Log.d(TAG,format( 'New Message from {color.blue}${message.fromJid?.userAtDomain}{color.end} message: {color.red}${message.body}{color.end}')); } }
- 修正在线状态监听的空断言问题
原代码在onPresence方法中直接对event.jid、fullJid使用强制非空断言,字段为空时直接崩溃。增加判空逻辑后再输出日志:
void onPresence(xmpp.PresenceData event) { final jidFull = event.jid?.fullJid; if (jidFull != null) { Log.d(TAG, 'presence Event from ' + jidFull + ' PRESENCE: ' + event.showElement.toString()); } }
- 修正发消息逻辑的时序错误
原sendmessageforxmpp方法中,刚初始化连接对象就直接调用发消息接口,此时连接未建立、内部模块未初始化,必然触发空异常。需要等待连接状态变为Ready后再执行发消息操作:
sendmessageforxmpp() async { var userAtDomain = 'xxx@gmail.com'; var password = 'password'; var jid = xmpp.Jid.fromFullJid(userAtDomain); var account = xmpp.XmppAccountSettings(userAtDomain, jid.local, jid.domain, password, 5222, resource: 'xmppstone'); var connection = xmpp.Connection(account); var receiver = 'yyy@gmail.com'; var receiverJid = xmpp.Jid.fromFullJid(receiver); Log.d(TAG, receiverJid.fullJid.toString()); // 发起连接 connection.connect(); // 等待连接就绪再发消息 await for (final state in connection.connectionStateStream) { if (state == xmpp.XmppConnectionState.Ready) { var messageHandler = xmpp.MessageHandler.getInstance(connection); messageHandler.sendMessage(receiverJid, "str"); break; } } }
- 替换阻塞式延迟方法
原代码在异步回调中使用sleep会阻塞整个Dart事件循环,导致网络请求、模块初始化流程卡住,极易触发内部状态未初始化的空错误。所有sleep调用全部替换为非阻塞的Future.delayed:
// 替换原有的 sleep(const Duration(seconds: 1)); await Future.delayed(const Duration(seconds: 1));
- 清理冗余判空逻辑
原代码判断vCard != null后又重复判断一次vCard非空,直接删除内层重复的vCard判空即可,不影响逻辑。
内容的提问来源于stack exchange,提问作者Manivannan Kumar
相关产品推荐
相关产品推荐

