1、 前言
我们这群被称作"码农"的生物,总能在混乱与秩序之间找到微妙的平衡。即便私生活很混乱,也要让每个字符优雅如诗------这就是当代Android开发者特有的浪漫主义。
2、bug描述
上一篇文章,我让异常日志,显示到界面上之后,我们工厂的同志就开始测试了。测了一天,临下班告诉我,App偶发崩溃让我瞧一瞧。
程序最害怕的是什么bug,就是偶发的bug,因为偶发的bug不容易调试。这是最烦的。不过还好,我把报错的异常堆栈信息,显示到页面上了,让我们的同志发给我了。如果你还不会,坐飞机过去# 为了方便测试,程序每次崩溃的时候,我都让他跳转新页面,把日志显示出来 观察日志发现是最简单的bug,NUll Pointer Exception。
3、代码逻辑
我是上位机,接到下位机的CAN消息之后,会把CAN消息通过Socket转发给PC端,每次发送消息,都会关闭Socket连接,下次发送的时候,再重新连接,发送新的Socket消息 就是在获取socket连接状态时,发生了空指针。上代码
伪代码
kotlin
socketScope.launch() {
if(!mManager.isConnected){
mManager.connect()
}
mManager?.sendData(data)
}
按道理没啥问题,可是发现工作站在我每次发完消息,就会断开连接。 Socket我用的框架,我就去着手去查看框架在关闭连接时候的源代码。
这时发现,disconnect的操作是开了一个线程的。至此,导致bug的原因已经找到了。 我在协程的代码执行到连接之后,这个代码diconnect整好执行完,socket被回收被置null,导致我发送数据的时候,直接空指针。多线程导致的线程不安全问题。
4、修改bug
- 为了减少Socket的频繁创建和销毁,让PC端改成了长链接,不要动不动就关闭我的连接。
- 然后定时发送心跳包,发送异常,更新连接状态。socket不置null,重新连接。
- 发送数据,发送失败,不要重发,丢弃。因为涉及到机器状态显示,要显示最新值。如果重发会导致信息回覆盖最新值。
- 协程添加异常处理Handler,发生异常的时候,不要崩溃,记录或处理异常。类似try-catch
5、总结
多线程的问题不是很好找。幸亏我把日志收集起来,展示出来了,不让还不知道找到啥时候呢这个bug。协程和线程共用的时候一点要小心。
什么,线上的bug导致用户无法使用,你为了安抚女朋友,四十分钟之后,才开始寻找bug!!!!