IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 解决Android Handler的handleMessage()方法内TextView.setText偶尔不执行的问题 -> 正文阅读

[移动开发]解决Android Handler的handleMessage()方法内TextView.setText偶尔不执行的问题

前言

最近项目中要加一个体温测量的外设模块 利用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次循环
得到的结果是正确的 没有漏掉一次
1

如上述结果 是我想要的 所以按照这种实现流程我测试了代码执行
结果还是有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置空 防止内容泄漏");
        }
    }

1

体温测量

体温测量是一个模块 需要用到串口通信 来传输测量到的体温数据 如何处理数据就要靠自己分析
一般厂家有个文档 需要一点点摸索
2

总结

最近在项目中学习了android的串口通信 感觉收获不错
一开始在测量体温数据时 偶尔拿不到页面渲染 本想就这样算了
但是本着一追到底的精神 彻底解决这个问题后心情愉悦

今天是中国民间的传统节日七夕节 没有对象 只能对知识追求探索
加油吧 不忘初心 方得始终
flight

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:43:16  更:2021-08-15 15:43:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:44:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码