当前位置: 首页 > news >正文

Android-Handle消息传递和线程通信

本文为作者学习笔记,如有误,请各位大佬指点

目录

一、同步异步

二、Java多线程通信

三、Handler是什么

四、Handler相关的类

五、Handler常用方法

1. 发送消息

2. 接收处理消息

3. 切换线程

六、使用Handler

使用Handler更新UI

使用Handler延时更新UI

使用Handler消息传递

使用Handler消息延迟传递

Handler移除功能

Handler消息拦截

七、Handler原理

八、线程、looper、messageQueue、Handler的数量级关系

九、Handler案例-倒计时


一、同步异步

同步:一个进程在执行某个请求时,如果该请求需要一段时间才能返回信息,那么这个进程会一直等待下去,直到收到返回信息才继续执行下去。

异步:异步是指进程不需要一直等待下去,而是继续执行下面的操作,不管其他进程的状态,当有信息返回的时候会通知进程进行处理,这样就可以提高执行的效率了,

并发:多个任务在同一个时间段进行,在同一时刻,其实只有一个任务在进行。即在一台处理器上“同时”(同时间段)处理多个任务。

并行:多个任务在同一时刻发生,把每一个任务分配给每一个处理器独立完成。在同一时刻,任务一定是同时运行。并行在多台处理器上分别同时处理多个任务。

二、Java多线程通信

Java 中有很多种方法实现线程之间相互通信访问数据,比如:

  • 通过 synchronized 关键字以“上锁”机制实现线程间的通信。多个线程持 有同一个对象,他们可以访问同一个共享变量,利用 synchronized“上锁” 机制,哪个线程拿到了锁,它就可以对共享变量进行修改,从而实现了通信。

  • 使用 Object 类的 wait/notify 机制,执行代码 obj.wait();后这个对象 obj 所在的线程进入阻塞状态,直到其他线程调用了 obj.notify();方法 后线程才会被唤醒。

三、Handler是什么

  • 更新UI

    当后台任务完成时,通过handler将结果发送到UI线程,以更新UI界面,比如显示加载完成的数据、更新进度条等。

  • 实现消息传递和线程通信的

    Android应用通常会涉及到多个线程的并发执行,通过Handler,在不同线程间发送消息和处理消息,实现线程间的通信,比如主线程和后台线程之间的通信。

  • 解决多线程并发

    假设如果在一个Activity当中,有多个线程去更新UI,并且都没有加锁机制,就会产生更新界面错乱。

    如果对更新UI的操作都进行加锁处理又会使应用性能下降,

    所以Android给我们提供了handler,只需要遵循这样的机制就可以了,根本不用去关心多线程问题,都是在主线程的消息队列当中去轮询处理的。

  • 定时任务处理

    可以使用Handler的postDelayed()方法来延迟执行代码块或发送延时消息。

    这对于实现定时刷新、定时执行任务等场景非常有用。

四、Handler相关的类

Handler:发送和接收消息

Looper:轮询消息队列,一个线程只能有一个Looper

Message:消息实体

MessageQueue:消息队列 用于存储消息和管理消息

五、Handler常用方法

1. 发送消息

  • boolean sendMessage (Message msg)

    发送一条消息

  • boolean sendMessageDelayed (Message msg, long sendMessageDelayed )

    在过了 delayMillis 毫秒之后发送一条消息。

  • boolean sendMessageAtTime (Message msg, long uptimeMillis)

    在具体指定的时间 uptimeMillis 发送一条消息。uptimeMillis 为系统开机到当 前的时间(毫秒)。

  • boolean sendEmptyMessage (int what)

    发送一个只有消息标识 waht 的空消息。该方法适用于不需要传递具体消息只是 单独的发通知时。

    boolean sendEmptyMessageDelayed (int what, long delayMillis)

    在过了 delayMillis 毫秒之后发送一个只有消息标识 waht 的空消息。

  • boolean sendEmptyMessageAtTime (int what, long uptimeMillis)

    在具体指定的时间 uptimeMillis 发送一个只有消息标识 waht 的空消息。 uptimeMillis 为系统开机到当前的时间(毫秒)

2. 接收处理消息

  • void handleMessage (Message msg)

    处理消息的方法。该方法通常用于被重写。

  • final boolean hasMessages(int what)

    检查消息队列中是否包含what属性为指定值的消息。

  • final boolean hasMessages(int what, Object object)

    检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息。

  • 多个重载的Message obtainMessage()

    获取消息。

3. 切换线程

  • boolean post (Runnable r)

    Runnabler会运行在 handler 对象被创建的线程上。当我们在 UI 线程创建了 Handler 对象,在 Worker 线程调用 handler.post()方法时,Runnable 就会运行 在 UI 线程中。

  • boolean postAtTime (Runnable r, long uptimeMillis)

    在具体指定的时间 uptimeMillis 让 Runnable 运行在 Handler对象被创建的线程 中。

  • boolean postDelayed(Runnable r, long delayMillis)

    在具体指定的时间 delayMillis 之后让 Runnable 运行在 Handler 对象被创建的 线程中

六、使用Handler

使用Handler更新UI

  • 定义handler

    privite Handler handler = new Handler();
  • 定义runnable

    Runnable runnable = new Runnable(){public void run(){textView.setText("cx")}
    };
  • 启动runable

    handler.post(runnable);

使用Handler延时更新UI

  • 定义handler

  • 定义runnable

  • 启动runable

    handler.postDelayed(runnable,2000);//延时2秒更新UI
  • 发送延时通知

    handler.sendEmptyMessageDelayed(what,2000);

使用Handler消息传递

  • 创建消息(可以创建不同类型的消息)

    //Message mes = handler.obtainMessage()
    Messagae mes = new Message();
    mes.arg1=66;
    mes.arg1=32;
    mes.obj="djka";
    //发送消息
    //或者mes.sendToTargrt();
    handler.sendMessage(mes);
  • 接收并处理消息

    privite Handler handler = new Handler(){public void handlerMessage(Message message){textViw.setText( (String)message.obj + message.arg1 +  message.arg2);}
    };

使用Handler消息延迟传递

  • 创建消息(可以创建不同类型的消息)

    handler.sendMessageDelayed(mes);
  • 接收并处理消息

Handler移除功能

比如在延时更新UI过程中移除,只是UI不再显示,

handle.removeCallbacks(runnable);

Handler消息拦截

  • 消息接收

    private Handler handler = new Handler(new Callback() {public boolean handleMessage(Message msg) {Toast.makeText(getApplicationContext(), "1", 1).show();return true;//返回false,执行完上面的代码在执行下面的;返回true,则不再执行下面的代码}}){public void handleMessage(Message msg) {Toast.makeText(getApplicationContext(), "2", 1).show();}
    };
  • 发送一个空消息

    handler.sendEmptyMessage(1);

七、Handler原理

  • Handler负责发送消息,Looper负责接收Handler发送的消息,并直接把消息传给handler自己,MessageQueue就是一个存储消息的容器。

    • Handler

      是消息处理器,负责接收和处理消息。

      每个Handler实例都关联一个特定的线程,并与该线程的消息队列关联。

      可以发送和处理消息,实现线程间的通信。

    • Message

      Handler传递的消息对象,用于在不同线程之间传递数据。

      包含要传递的数据和附加消息(消息类型、标志等)。

      通过Handler的sendMessage()方法发送到目标线程的消息队列中,并在目标线程中被处理

    • Looper

      消息循环器,用于管理线程的消息队列。

      每个线程只能有一个Looper对象,负责不断地读取队列中的消息,并将消息通过Handler的dispatchMessage()传递给对用的Handler进行处理。

  • Handler工作原理

    • 当一个线程需要使用Handler来处理消息时,首先创建一个Looper对象:

      在ActivityThread中的main方法中,系统调用Looper.prepareMainLooper(),调用其prepare()创建一个与当前线程关联的消息队列。

      prepare(boolean quitAllowed) quitAllowed的作用是在创建MessageQueue时,标识消息队列是 否可以销毁, 主线程不可被销毁

    • 通过Looper的loop()启动消息循环,读取消息队列中的消息。

    • 当有消息通过Handler的sendMessage()发送到消息队列时,Looper会不断从消息队列中读取消息,并传递给对用的Handler进行处理。

    • Handler接收到消息后,调用自己的handleMessage()来处理消息。

Handler消息处理流程

message中callback是一个Runnable对象,如果callback不为空,则直接调用callback的 run方法,

否则判断mCallback是否为空,mCallback在Handler构造方法中初始化,在主线程通直接通过无参的构造方法new出来的为 null,所以会直接执行后面的handleMessage()方法。

public void dispatchMessage(Message msg) {//callback在message的构造方法中初始化或者使用handler.post(Runnable)时候才不为空if (msg.callback != null) {handleCallback(msg);} else {//mCallback是一个Callback对象,通过无参的构造方法创建出来的handler,该属性为null,此段不执行if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);//最终执行handleMessage方法}
}
private static void handleCallback(Message message) {message.callback.run();
}

八、线程、looper、messageQueue、Handler的数量级关系

一个 Thread 只能有一个 Looper,一个 MessageQueen,可以有多个 Handler 以一个线程为基准,他们的数量级关系是: Thread(1) : Looper(1) : MessageQueue(1) : Handler(N)

九、Handler案例-倒计时

public class MainActivity extends AppCompatActivity {private TextView tv_aaa;
​@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv_aaa = findViewById(R.id.tv_aaa);//aaa();handler1.postDelayed(runnable,1000);}
​
/*    private Handler handler = new Handler() {@Overridepublic void handleMessage(@NonNull Message msg) {//tv_aaa.setText(msg.obj.toString());}};*/
​private int i=10;
​private Handler handler1=new Handler();
​private Runnable runnable=new Runnable() {@Overridepublic void run() {if (i > 0){tv_aaa.setText(i--+"");handler1.postDelayed(this,1000);}else {handler1.removeCallbacksAndMessages(null);}}};
​
​
/*private void aaa() {
​handler.postDelayed(new Runnable() {@Overridepublic void run() {for (int i = 10; i > 0; i--) {Log.d("xx", "run: ");Message message = new Message();//message.what = 0;message.obj = i;handler.sendMessageDelayed(message, (10-i) * 1000);}}}, 1000);
​
*/
/*new Thread(new Runnable() {@Overridepublic void run() {for (int i = 10; i > 0; i--) {Log.d("xxz", "run: ");Message message = new Message();message.what = 0;message.obj = i;handler.sendMessageDelayed(message, 1000);}
​}}).start();*//*
​}
*/
​//Handler handler = new Handler(){//    @Override//    public void handleMessage(@NonNull Message msg) {//        super.handleMessage(msg);//        switch (msg.what){//            case 0://                tv_aaa.setText(msg.obj+"");//        }//    }//};
}

相关文章:

Android-Handle消息传递和线程通信

本文为作者学习笔记,如有误,请各位大佬指点 目录 一、同步异步 二、Java多线程通信 三、Handler是什么 四、Handler相关的类 五、Handler常用方法 1. 发送消息 2. 接收处理消息 3. 切换线程 六、使用Handler 使用Handler更新UI 使用Handler延…...

【Kubernetes】常见面试题汇总(四十七)

目录 106.考虑一种情况,公司希望通过保持最低成本来提高效率和技术运营速度。您如何看待公司将如何实现这一目标? 107.假设一家公司想要修改其部署方法,并希望构建一个可扩展性和响应性更高的平台。您如何看待这家公司能够实现这一目标以满足…...

grafana全家桶-loki promtail收集k8s容器日志

loki是grafana旗下轻量级日志收集工具,为了减少loki对集群的影响,把loki的agent日志收集端promtail部署在k8s集群中,loki server部署在集群外面。这样简单做一个解耦,避免大量读写的应用影响到集群内业务服务。 一、promtail部署…...

HTML5+CSS+JavaScript剪子石头布游戏

HTML5CSSJavaScript剪子石头布游戏 用HTML5CSSJavaScript剪子石头布游戏实现剪子石头布游戏,游戏有成绩计数,人、机输赢情况,及平局情况。 ✂代表剪刀,▉代表石头,▓ 代表布,给出人机双方的出拳情况 游戏…...

Flask-3

文章目录 ORMFlask-SQLAlchemySQLAlchemy中的session对象数据库连接设置常用的SQLAlchemy字段类型常用的SQLAlchemy列约束选项 数据库基本操作模型类定义 数据表操作创建和删除表 数据操作基本查询SQLAlchemy常用的查询过滤器SQLAlchemy常用的查询结果方法多条件查询分页器聚合…...

Redis的基本使用

简介 传统的数据库是 关系数据库,但是Redis是键值对数据库传统的数据库是基于 磁盘存储的,但是Redis是基于 内存存储的 基于内存,读写性能更高内存是不大的,只能存储热点信息 安装 绿色软件,安装即可使用 安装服务 手…...

[241004] Linux 系统中配置文件的区别 | VirtualBox 7.1.2 发布,修复多项问题并提升性能

目录 Linux 系统中 /etc/profile, ~/.bash_profile, ~/.profile, ~/.bashrc 等配置文件的区别一、配置文件类型二、配置文件作用三、交互式登录 Shell 和非登录 Shell交互式登录 shell交互式非登录 shell 四、配置文件加载顺序五、~/.bash_profile 和 ~/.bashrc 的区别 Virtual…...

hbuilderx+uniapp+Android宠物用品商城领养服务系统的设计与实现 微信小程序沙箱支付

目录 项目介绍支持以下技术栈:具体实现截图HBuilderXuniappmysql数据库与主流编程语言java类核心代码部分展示登录的业务流程的顺序是:数据库设计性能分析操作可行性技术可行性系统安全性数据完整性软件测试详细视频演示源码获取方式 项目介绍 顾客 领养…...

SVN 迁移到 GIT,并保留提交记录

1&#xff09;svn账号与git账号映射 创建 user.txt &#xff0c;格式如下&#xff0c;user.txt 放置在git base here 所选目录下即可 schacon Scott Chacon <schacongeemail.com> selse Someo Nelse <selsegeemail.com> 为了获得 SVN 使用的作者名字列表&#xf…...

【数据结构与算法】LeetCode:堆和快排

文章目录 LeetCode&#xff1a;堆和快排排序数组数组中的第K个最大元素 &#xff08;Hot 100&#xff09;前 K 个高频元素&#xff08;Hot 100&#xff09;数据流的中位数&#xff08;Hot 100&#xff09; LeetCode&#xff1a;堆和快排 排序数组 排序数组 双向切分实现快排…...

文档大师:打造一站式 Word 报告解决方案

前言 在政府、医院、银行、财务以及销售等领域&#xff0c;常常需要创建各种报告文件来展开工作汇报&#xff0c;譬如季度销售报告、年度总结报告、体检报告和保险合同等。在没有报表工具支持之前&#xff0c;这类报告主要通过 Word 制作&#xff0c;费时费力且难以维护&#…...

Python 数字专题:全方位解析整数

目录 1. 引言 2. 整数的基本概念 2.1 定义 2.2 整数的表示 2.3 创建整数 3. 整数的基本操作 3.1 算术运算 3.2 比较运算 3.3 位运算 4. 内置函数与方法 4.1 int() 函数 4.2 abs() 函数 4.3 pow() 函数 5. 整数的性能优化 5.1 大整数的处理 5.2 使用 numpy 6. 应…...

IP协议报文

一.IP协议报头结构 二.IP协议报头拆解 1.4位版本 实际上只有两个取值&#xff0c;分别是4和6&#xff0c;4代表的是IPv4&#xff0c;6代表的是IPv6。 2.4位首部长度 IP协议报头的长度也是边长的&#xff0c;单位是*4&#xff0c;这里表示的大小为0~15&#xff0c;当数值为1…...

【分布式微服务云原生】掌握分布式缓存:Redis与Memcached的深入解析与实战指南

掌握分布式缓存&#xff1a;Redis与Memcached的深入解析与实战指南 摘要&#xff1a; 本文深入探讨了分布式缓存在现代分布式系统中的重要性&#xff0c;详细分析了Redis和Memcached两种主流的分布式缓存解决方案的原理和使用场景。文章不仅提供了核心技术的深入解析&#xff…...

计算机毕业设计 基于Python的智能文献管理系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

如何查看NVIDIA Container Toolkit是否配置成功

要确认 NVIDIA Container Toolkit 是否已成功配置&#xff0c;可以按照以下步骤进行检查&#xff1a; 1.检查 NVIDIA 驱动程序 首先&#xff0c;确保你的系统已经正确安装了 NVIDIA 驱动程序&#xff0c;并且可以识别你的 GPU。你可以使用 nvidia-smi 命令来进行检查&#xf…...

python全栈学习记录(二十一)类的继承、派生、组合

类的继承、派生、组合 文章目录 类的继承、派生、组合一、类的继承二、派生三、组合 一、类的继承 继承是一种新建类的方式&#xff0c;新建的类称为子类&#xff0c;被继承的类称为父类。 继承的特性是&#xff1a;子类会遗传父类的属性&#xff08;继承是类与类之间的关系&a…...

Go语言实现长连接并发框架 - 任务执行流

文章目录 前言接口结构体接口实现项目地址最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;上篇博客中我们实现了客户端的请求的实现&#xff0c;接下来我们要去实现对请求任务的处理&#xff0c;我们需要定义任务执行的流程 接口 trait/task.go type TaskFunc interfa…...

Flutter与原生代码通信

文章目录 1. 知识回顾2. 示例代码3. 经验总结我们在上一章回中介绍了通道相关的内容,本章回中将介绍其中的一种通道:MethodChannnel.闲话休提,让我们一起Talk Flutter吧。 1. 知识回顾 我们在上一章回中介绍了通道的概念和作用,并且提到了通道有不同的类型,本章回将其中一…...

每日读则推(三)

n.(事件的)发生地点,(活动的)场所 n.雄性大园丁鸟 n.多细枝的,苗条的 v.放大,扩大(声音);增强,加强 Male great bowerbirds build twiggy concert venues that amplify their raucous songs and n.园丁鸟 …...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...