控制Arduino的App中readline()循环无操作时无异常终止问题
解决服务器等待消息循环意外终止的问题
嘿,我一眼就注意到你的循环终止问题大概率出在input.readLine()这个调用上——当没有输入的时候,它要么返回null,要么抛出未捕获的异常,直接把你的无限循环给打断了。咱们来一步步捋清楚问题,再给你几个修复方案:
问题根源分析
- 空指针异常:
readLine()在输入流关闭、连接断开或者长时间没有数据时会返回null,这时候你直接执行message.equals("END"),就会触发NullPointerException,程序直接跳出循环甚至崩溃。 - 初始值未定义:如果
message在进入循环前没有初始化,第一次执行message.equals("END")时也会直接空指针。
修复方案
方案一:添加空值检查与异常捕获
修改后的代码会先处理readLine()返回的null,同时捕获可能的IO异常,避免循环意外终止:
// 先初始化message,避免第一次循环空指针 String message = ""; for(;;) { // 先判断message不为null,再检查是否是终止指令 if (message != null && message.equals("END")) { break; } message = ""; switch (arduinoState) { case 1: sendMessage("Server[Cmd]: fwd"); arduinoState = 0; break; case 2: sendMessage("Server[Cmd]: right"); arduinoState = 0; break; case 3: sendMessage("Server[Cmd]: bwd"); arduinoState = 0; break; case 4: sendMessage("Server[Cmd]: left"); arduinoState = 0; break; case 5: sendMessage("Server[Cmd]: kante"); arduinoState = 0; break; } try { message = input.readLine(); // 处理输入流断开的情况 if (message == null) { updateStatusHandler.post(new updateStatusThread("Arduino连接已断开", true)); // 这里可以选择重连或者退出循环,根据你的需求调整 // break; continue; // 如果想保持循环等待重连,用continue } updateStatusHandler.post(new updateStatusThread("Arduino: " + message, false)); } catch (IOException e) { updateStatusHandler.post(new updateStatusThread("读取消息出错: " + e.getMessage(), true)); // 捕获异常后可以选择继续循环,避免直接终止 continue; } }
方案二:使用安全的equals方法
Java的Objects.equals()可以避免空指针,它会先判断两个参数是否为null,再比较内容。你可以把message.equals("END")改成:
if (Objects.equals(message, "END")) { break; }
不过这个方法只是避免了空指针,你还是需要处理readLine()返回null的情况,因为这通常意味着连接出现了问题。
额外建议
- 添加超时机制:如果你的输入流支持设置超时(比如SerialPort或者Socket),可以设置一个合理的超时时间,比如
input.setTimeout(3000);,这样长时间没数据时会抛出超时异常,你可以在catch块里继续循环,而不是一直阻塞。 - 线程安全处理:如果
arduinoState是被UI线程修改的(从updateStatusHandler来看应该是Android环境),记得给arduinoState加上volatile修饰符,或者用同步块,避免多线程下的状态不一致问题。 - 日志调试:可以在关键位置添加日志输出,比如
System.out.println("当前message值: " + message);,方便你排查循环终止的具体原因。
内容的提问来源于stack exchange,提问作者Sorata Kanda
相关产品推荐
相关产品推荐

