如何解决String类型空引用引发的java.lang.NullPointerException
解决Mqtt发送时的NullPointerException问题
看起来你踩了一个典型的时机逻辑错误,不是单纯的变量初始化问题,咱们一步步拆解清楚:
问题根源
你的payload1变量确实未初始化,但更核心的问题是逻辑时机不对:
- 你在Mqtt连接成功后立刻调用了publish,但这时候开关的
OnCheckedChangeListener还没被触发过(只有用户手动点击开关才会触发回调),所以payload1还是默认的null值,调用getBytes()直接抛出空指针异常 - 你之前的判空处理虽然避免了崩溃,但因为初始状态下
payload1是null,所以设备完全收不到初始的开关状态消息
修复方案
1. 先给payload1绑定初始值
因为你的开关默认设置为setChecked(true),所以初始化时直接对应默认状态:
// 类成员变量初始化时直接赋值 String payload1 = "ledOn";
2. 调整消息发送的逻辑位置
把消息发送的代码移到开关状态变化的回调里,同时在连接成功后主动触发一次状态处理,确保初始状态的消息能正常发送:
@Override public void onSuccess(IMqttToken asyncActionToken) { String topic = "rpi/gpio"; switchLed.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // 更新payload值 payload1 = isChecked ? "ledOn" : "ledOff"; // 发送消息 try { MqttMessage message1 = new MqttMessage(payload1.getBytes()); client.publish(topic, message1); } catch (MqttException e) { e.printStackTrace(); // 这里可以加个Toast提示用户消息发送失败 } } }); // 连接成功后,主动触发一次开关状态处理,发送初始消息 switchLed.performClick(); // 也可以直接手动发送初始消息,避免模拟点击: // try { // MqttMessage message1 = new MqttMessage(payload1.getBytes()); // client.publish(topic, message1); // } catch (MqttException e) { // e.printStackTrace(); // } }
为什么你之前的尝试无效?
- 用
new String("ledOn")赋值本身没问题,但这个赋值动作只有在开关被点击时才会执行,连接成功后的第一次publish依然拿的是null值 - 判空处理直接跳过了初始的publish请求,导致设备收不到最开始的开关状态
额外优化建议
- 可以把
payload1的初始化和开关状态绑定,避免硬编码不一致:String payload1 = switchLed.isChecked() ? "ledOn" : "ledOff"; - 不要忽略
MqttException,至少打印日志或者给用户反馈,方便排查问题 - 如果不需要持久化
payload1的状态,甚至可以直接去掉这个成员变量,在回调里直接生成消息:
// 去掉类成员变量payload1,直接在回调里生成消息内容 MqttMessage message1 = new MqttMessage(isChecked ? "ledOn".getBytes() : "ledOff".getBytes());
内容的提问来源于stack exchange,提问作者Tia
相关产品推荐
相关产品推荐

