前言
最近项目中要加一个体温测量的外设模块 利用android的串口通信 可以完美的取到测量的体温数据 获取到数据后,在用Handler发送数据到View渲染时 发现一个问题 就是数据能测量到 但是渲染到 TextView时有时无!
android串口通信CH340转USB android串口通信CH340转USB(可参考)
handleMessage
在使用Handler 通信时,handleMessage() 这个方法内渲染TextView数据 偶尔会丢失数据渲染 这个问题出发,寻找解决方案:
看到这样一个关于Handler+Thread 的例子
class MyThread implements Runnable{
int count = 0;
public void run() {
while(count <= 20){
try {
//每次休眠0.5秒
Thread.sleep(500);
}catch (Exception e){
e.printStackTrace();
}
//从消息池中获得消息,如果没有消息,创建一个消息,如果有,则取出来,由handler发送
Message message = Message.obtain();
message.arg1 = count;
message.obj = "jack";
handler.sendMessage(message);
count++;
}
}
Handler类如下:
class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int arg1 = msg.arg1;
//接收传过来的数据
String name = (String)msg.obj;
//渲染TextView数据
textView.append(name+arg1);
}
}
TextView渲染的结果 从图中可以看到 count <= 20,count++ 一共执行21次循环 得到的结果是正确的 没有漏掉一次
如上述结果 是我想要的 所以按照这种实现流程我测试了代码执行 结果还是有TextView漏掉渲染的问题
将Handler设置为静态对象
在翻阅资料的时候 看到这样一个说明
不在执行的问题原因: onCreate()方法不是每次启动界面都会执行的,当界面使用finish() 后界面被保存到堆栈。 第二次启动该界面时是不会在执行onCreate()方法的,而且在这之前也没有保存该界面对象的原型。 所以在finish()后实际上handler和loop都是空的。所以不会执行。 处理方法: 1.将对象handler做为静态对象使用。
于是 重新修改代码 将handler 设置为静态对象
public static Handler handler;
依然是在Activity的onCreate()方法中初始化Handler后渲染TextView数据
handler = new Handler() {
public void handleMessage(Message msg) {
// 截取返回值中的体温数据
currentTemp1 = (String) msg.obj;
//拿到当前的体温 数据渲染数据到页面上显示
setTemperatureDataRealTime(currentTemp1);
}
};
在读体温数据时,我的代码是这样处理的 每次休眠1秒防止数据发送过快
private class readThread extends Thread {
public void run() {
byte[] buffer = new byte[4096];
while (true) {
try {
//每次读取数据 休眠1秒
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
//从消息池中获得消息,如果没有消息,创建一个消息,如果有,则取出来,由handler发送
Message msg = Message.obtain();
int length = MyDriverManager.driver.ReadData(buffer, 4096);
if (length > 0) {
String recv = toHexString(buffer, length);
//以16进制输出
// String recv = new String(buffer, 0, length); //以字符串形式输出
msg.obj = recv.replace(" ", "");
handler.sendMessage(msg);
}
}
}
}
以上代码处理数据接收 以及数据发送 没有问题 但是在体温测量这个页面关闭的时候 会有个bug提醒
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.os.Handler.sendMessage(android.os.Message)' on a null object reference
这是一个空指针异常 是handler造成的
代码优化后是这样的写法 对handler和msg都做了一层!=null判断
private class readThread extends Thread {
public void run() {
byte[] buffer = new byte[4096];
while (true) {
try {
//每次读取数据 休眠0.1秒
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
//从消息池中获得消息,如果没有消息,创建一个消息,如果有,则取出来,由handler发送
Message msg = Message.obtain();
int length = MyDriverManager.driver.ReadData(buffer, 4096);
if (length > 0) {
String recv = toHexString(buffer, length); //以16进制输出
if (msg != null) {
if (handler != null) {
msg.obj = recv.replace(" ", "");
handler.sendMessage(msg);
} else {
Log.e(TAG, "handler ------ 没有初始化 handler = null");
}
} else {
ALog.e(TAG, "sendMessage ------ 需要发送Message为空");
}
}
}
}
}
关于内存泄漏
在体温测量这个页面 静态使用Handler对象 可能会造成内存泄漏 我的处理方法是在onDestroy()方法内把handler对象置空 并且发送空数据 停止接收
@Override
protected void onDestroy() {
//结束前关闭串口
MyDriverManager.driver.CloseDevice();
super.onDestroy();
EventBus.getDefault().unregister(this);
if (handler != null) {
handler.removeCallbacksAndMessages(null);
handler = null;
ALog.e(TAG, "------ 把Handler置空 防止内容泄漏");
}
}
体温测量
体温测量是一个模块 需要用到串口通信 来传输测量到的体温数据 如何处理数据就要靠自己分析 一般厂家有个文档 需要一点点摸索
总结
最近在项目中学习了android的串口通信 感觉收获不错 一开始在测量体温数据时 偶尔拿不到页面渲染 本想就这样算了 但是本着一追到底的精神 彻底解决这个问题后心情愉悦
今天是中国民间的传统节日七夕节 没有对象 只能对知识追求探索 加油吧 不忘初心 方得始终
|