Android的handler消息收发处理——子线程与主线程(UI线程)间的通信

news/2024/5/17 10:36:19/文章来源:https://blog.csdn.net/PHILICS7/article/details/126644326

 

目录

写在前面 

基础概念

什么是handler?

什么是looper?

什么是消息队列(MessageQueue)?

在子线程中使用子线程中的数据更新UI线程

主线程与子线程通信实例(程序代码)

 子线程获取主线程handler发送数据给主线程。

 主线程发信息给子线程


写在前面 

时间截止到2022年9月2日。(为什么说明时间,因为安卓在不断地更新不断地完善,今天能跑的代码放到明天不一定能正常运行,因为安卓完善可能会因为性能原因舍弃掉某些功能的实现或者是以新的算法来优化原来的功能)

基础概念

在其他线程中更新UI界面被安卓认为是不安全的,安卓是不允许的,UI线程(主线程)当然可以更新UI界面,于是可以通过其他线程发数据(通信内容)给UI线程让其帮忙更新数据。

什么是handler?

handler主要接受子进程的发送的数据,并用此数据配合主线程更新UI.

以我个人使用而言,见字面意思,它是一个消息处理类。使用必须重写其中的handleMessage(Message  msg)方法,一个线程如果获得了另一个线程的handler对象,则能通过另一个线程的handler.sendxxx发送信息。

Message msg 的常用属性有 

.obj (Object类型)   可以是任意类型的数据,取出来后再强制转换即可。

 .what(int类型)我个人使用用于判断由那个控件产生的事件引起的通信。

目前handler的空参构造已经被废弃,可以通过指定的looper来进行构造。

#例如在主线程中构造handler

  private Handler mHandler= new Handler(Looper.getMainLooper()) {@Override//重写handleMessage方法,根据msg中what的值判断是否执行后续操作public void handleMessage(Message msg) {if (msg.what == 0) {i++;runt.setText(String.valueOf(i));}}};

什么是looper?

        正如上面的handler可以发送消息,Message(消息)由一个消息队列进行管理,而消息队列又是由一个looper进行管理的,Looper负责管理线程的消息队列和消息循环,在主线程中自动创建了一个looper,而其他子线程则需要自己手动创建。

        在主线程中,通过Loop.getMainLooper可以获得主进程的Looper对象。

        在子进程中,先Looper.prepare()创建消息队列,再通过Loop.myLooper得到当前线程的Looper对象,最后通过Looper.loop进入消息循环。

   

总结:     

 handler与looper是唯一映射的关系;

一个handler只能拥有一个looper;

一个looper只能和一个线程相照应,同时一个looper也对应着唯一一个MessageQueue。  
 一个looper却可以拥有多个handler (因为handler可以通过指定looper来创建)

 

比如在子线程中创建handler

  class Ctrl extends Thread {public  Handler Chandler;public  Looper Clooper =Looper.myLooper();public  void    run(){Looper.prepare();Chandler=new Handler(Clooper){@Overridepublic void handleMessage(Message msg) {if(msg.what== 0){Log.e(TAG, "子线程收到消息" );}}};Looper.loop();}}


 

什么是消息队列(MessageQueue)?

它是由Looper这个管理类所维护的,handler分发一个消息,消息队列中的消息加1,Looper.loop不断从队头取出消息供handler处理。

在子线程中使用子线程中的数据更新UI线程

使用方法

 MainActivity.this.runOnUiThread(new Runnable() // 重写其中run方法

比如

         MainActivity.this.runOnUiThread(new Runnable() {@Overridepublic void run() {runt.setText(time+"s");tl.setText(TempLimit);hl.setText(HumiLimit);ll.setText(LsLimit);isc.setText(_isc);temp.setText(_temp);humi.setText(_humi);ls.setText(_ls);if(cons)state.setText("已连接");else {state.setText("断开连接");state.setTextColor(R.color.red);}}});

主线程与子线程通信实例(程序代码)

 子线程获取主线程handler发送数据给主线程。

在UI中的oncreate中

  mhandler=new Handler(Looper.getMainLooper()){@Overridepublic void handleMessage(Message msg) {if(msg.what==0){Log.e(TAG, "主线程收到消息:"+(String) msg.obj );}}};

在子线程中

 class Ctrl extends Thread {Message msg;public  void  run(){while (true){try {Thread.sleep(1000);msg=new Message();msg.what=0;msg.obj="hello";mhandler.sendMessage(msg);} catch (InterruptedException e) {e.printStackTrace();}}}}
}

 效果:

 主线程发信息给子线程

值得注意的是,子线程的handler需要在子线程中创建looper,通过

Looper.prepare();

创建。

 具体代码

package com.example.yuezhenhao;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;import java.util.Timer;
import java.util.TimerTask;import javax.security.auth.Subject;//
public class UIshow extends AppCompatActivity {private  String TAG="UIshow";private  Handler subandler;  //子线程handler对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_uishow);Ctrl  ctrlthread=new Ctrl();ctrlthread.start();new Timer().schedule(new TimerTask() {@SuppressLint("ResourceAsColor")@Overridepublic void run() {if(subandler != null) subandler.sendEmptyMessage(0);}},0,1000);}///子线程class Ctrl extends Thread {public  Handler Chandler;public  void    run(){Looper.prepare();Chandler=new Handler(Looper.myLooper()){@Overridepublic void handleMessage(Message msg) {if(msg.what== 0){Log.e(TAG, "子线程收到消息" );}}};if(subandler == null) {subandler= Chandler;}Looper.loop();}}}

效果: 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_4879.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

01.Singleton单件(单例)

一&#xff1a;动机&#xff08;Motivation&#xff09; <1>在软件系统中&#xff0c;经常有这样一些特殊的类&#xff0c;必须保证它们在系统中只存在一个实例&#xff0c;才能确保它们的逻辑正确性、以及良好的效率。 <2>如何绕过常规的构造器&#xff0c;提供一…

堆技巧 数组反向越界泄露地址

四川省2021信息安全技术大赛 classroom 痛苦痛苦痛苦&#xff0c;调了半天才找到数组起始地址&#xff0c;还是自己太菜了&#xff0c;好好记录一下这题 题目给了libc&#xff0c;2.31的题 嗯&#xff0c;可以考虑覆盖got表或者hook函数 打开ida发现是c的题&#xff0c;认真…

目前期货开户手续费比较透明

一、期货公司手续费 只要交易买卖期货就会产生期货手续费&#xff0c;不同的期货交易所&#xff0c;商品期货手续费收取标准不一样&#xff0c;首先&#xff0c;我们需要弄清楚期货手续费的组成和分类&#xff1a; 期货实际收取的手续费期货交易所手续费期货公司额外加收的佣…

flask-sqlalchemy连接数据库

1、安装flask_sqlalchemy和pymysql包 pip install flask-sqlalchemy pip install pymysql 2、进行配置 使用Flask-SQLAlchemy扩展操作数据库&#xff0c;首先需要通过URL建立数据库连接&#xff0c;必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI中。 HOSTNAME 127.0…

MySQL入门:数据库是什么 | SQL是什么 | MySQL是什么

文章目录数据库数据库管理系统&#xff08;DBMS&#xff09;的种类数据库的结构什么是SQLMySQLSQL语句 | 种类SQL 的基本书写规则存储引擎参考与总结全文约 3235 字&#xff0c;预计阅读时长&#xff1a; 9分钟数据库 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库?…

dubbo和springCloud

Dubbo 高性能的java RPC框架 架构 init:初始化 async:异步 sync同步 0:需要容器启动例如Tomcat 1:注册ip端口以及一些东西到注册中心 2:订阅服务快速入门 Zookeeper(官方推荐注册中心,同时还有Redis,Simper,Multicast,Nacos等) 安装:默认端口2181 Dubbo快速入门 传统方法,需要…

C/C++后端开发学习路线总结(附带实习学习经历分享)

大家好哇&#xff0c;九月份了&#xff1b;不知道大家的工作或者实习都安排的怎么样了&#xff1f;反正狮作为一个过来人只能在各种论坛上面看到都是哀鸿遍野&#xff1b;暗自惊心感慨现在年轻人不好混啊~ 然后呢&#xff0c;狮最近后台收到不少C/C后端怎么学的邀请回答&#…

广西大学口袋开发板之抢答器

任务要求&#xff1a; 四名选手各有一个抢答按键&#xff0c;按键的编号以及指示灯&#xff08;手柄板上的LED模块&#xff09;的编号与选手的编号相对应&#xff0c;抢答器具有编号的识别和数据的锁存、显示以及提示音功能。 评分细则&#xff1a; 裁判按下开始键后&#x…

2022年0902Maven的继承和利用Idea创建Maven工程的内容<第五课>

目录 第一部分 Maven的继承 1 概念 2 作用 3 它的背景是&#xff1a; 4 它背后的需求是&#xff1a; 在每一个 module 中各自维护各自的依赖信息很容易发生出入&#xff0c;不易统一管理。 使用同一个框架内的不同 jar 包&#xff0c;它们应该是同一个版本&#xff0c;所…

电脑无线5g网卡发现不了网件R7000的Wifi 5g网络

原因是因为 网件R7000的5g网络默认是100的频道&#xff0c; 把频道固定的153然后把路由器离拖线板和其他设备远一点

第十章Redis_主从复制

10.Redis_主从复制 文章目录10.Redis_主从复制10.1主从复制是什么?10.2主从复制能干嘛10.3怎么玩&#xff1a;主从复制10.3.1在根目录下创建myredis文件夹10.3.2复制/etc/redis.conf文件到myredis下&#xff0c;文件名和之前保持一致10.3.3配置一主两从&#xff0c;创建三个配…

687 最长同值路径——Leetcode 天天刷(2022.9.2)【DFS】

687 最长同值路径——Leetcode 天天刷&#xff08;2022.9.2&#xff09;【DFS】 文章目录687 最长同值路径——Leetcode 天天刷&#xff08;2022.9.2&#xff09;【DFS】前言题目描述示例提示信息本地调试运行输入格式输出格式输入样例输出样例层次遍历构造二叉树解法——DFS细…

新店速递丨白玉兰(商务)酒店赣榆吾悦广场店 正式上线

第242家 白玉兰酒店再下连云港 2022年9月&#xff0c;锦江酒店&#xff08;中国区&#xff09;旗下优选服务酒店品牌“白玉兰酒店”连云港再添一员&#xff0c;迎来门店——白玉兰&#xff08;商务&#xff09;酒店赣榆吾悦广场酒店正式上线。这也是全国第242家开业的白玉兰酒…

Git做版本管理及CHANGELOG

规范化的提交信息除了能很好描述项目的修改&#xff0c;还有一个很好的作用就是能根据提交记录来生成CHANGELOG.MD和自动生成版本号等功能。 standard-version 一个用于生成CHANGELOG.md和进行SemVer(语义化版本号)发版的命令行工具 主要功能&#xff1a; 自动修改最新版本…

6-2 多项式求值——15分

本题要求实现一个函数,计算阶数为n,系数为a[0] … a[n]的多项式(上图) 在x点的值。 函数接口定义: double f( int n, double a[], double x );其中n是多项式的阶数,a[]中存储系数,x是给定点。函数须返回多项式f(x)的值。 裁判测试程序样例: #include <stdio.h>#def…

Docker - 容器的网络模式

目录 一、bridge模式 查看容器的有哪几种网络类型 二、host模式 三、none模式 四、container模式 五、overlay模式 创建一个桥接类型的网卡 使用刚才创建的网卡来创建容器 查看刚才使用网卡创建的容器的ip地址 我们指定网卡创建的容器IP地址是 &#xff1a;172.18.0.…

计算机网络——网络协议

目录 网络协议 网络协议的三要素 协议的分层模型 计算机网络层次结构的好处 计算机网络的体系结构 OSI与TCP/IP的体系结构的比较 网络协议 1、计算机网络中的数据交换必须遵守事先约定好的规则。 2、这些规则明确规定了所交换的数据的格式和时序&#xff0c;以及在发送或…

SpringBoot 整合 RabbitMQ 实现消息回调、手动确认 (二) 有图 有源码

创建时间 2022年8月29日 标签&#xff1a;Java、SpringBoot、RabbitMQ、队列 注释&#xff1a;新建SpringBoot项目实操RabbitMQ实现消息回调、手动确认 来源&#xff1a;CSDN博主&#xff1a;小目标青年 文章目录SpringBoot 整合 RabbitMQ 回调确认模式生产者推送消息回调1、消…

3天精通Postman---动态参数amp;断言amp;CSV数据驱动amp;Mock Server

DAY2课题&#xff1a;Postman接口关联&动态参数&断言&CSV数据驱动目录 一、接口关联&#xff0c;接口依赖&#xff0c;多接口串联&#xff0c;组合API 二、Postman的动态参数&#xff08;随机数&#xff09; 三、Postman的环境变量和全局变量 四、Postman断言 五、…

极端气候肆虐催化,碳中和带出了一个“再生时代”

江南一带的高温结束了&#xff0c;今年这场轰轰烈烈的高温&#xff0c;也画上了最后的句号。各地骤降的温度让人仿佛忘却了“热到爆表”的经历&#xff0c;但过去已经成为历史&#xff0c;历史充满痕迹。 格陵兰岛冰盖加速融化、欧洲莱茵河部分河段干涸、长江流域汛期反枯、重…