【Android】App通信基础架构相关类源码解析

应用通信基础架构相关类源码解析

这里主要对Android App开发时,常用到的一些通信基础类进行一下源码的简单分析,包括:

  • Handler:处理器,与某个Looper(一个线程对应一个Looper)进行关联。用于接收消息,并在关联的Looper,处理消息。
  • Looper:驱动器,驱动基于事件的消息系统(通信架构的核心)其实现在Native层,基于epoll机制(感兴趣的可自行了解)。
  • Runnable: 表示“可执行的代码”,本质是Interface,规定了Run这个接口。
  • MessageQueue: 消息队列,提供了入队、出队等操作。一个线程,只能有一个MessageQueue。
  • Thread: 线程类,封装了线程相关操作。

基于Android12代码。

类图:
在这里插入图片描述

Handler

常见用法

private Handler mHandler = new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {// 处理消息}
};private void sendMessage() {// 发送消息Message msg = mHandler.obtainMessage();// 填充msgmHandler.sendMessage(msg);
}private void postRunnable() {// 告知Handler一段可执行的代码(Runnable)mHandler.post(new Runnable() {@Overridepublic void run() {// do something}});
}

通过上述代码中,可以看出。创建Handler时需要绑定Looper,也就是绑定到运行的线程上。如过不指定looper,使用创建handler时所在线程的Looper。
源码定义在 frameworks/base/core/java/android/os/Handler.java

public Handler() {this(null, false);
}public Handler(@NonNull Looper looper) {this(looper, null, false);
}public Handler(@Nullable Callback callback, boolean async) {if (FIND_POTENTIAL_LEAKS) {final Class<? extends Handler> klass = getClass();if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&(klass.getModifiers() & Modifier.STATIC) == 0) {Log.w(TAG, "The following Handler class should be static or leaks might occur: " +klass.getCanonicalName());}}// 获取当前线程对应的LoopermLooper = Looper.myLooper();if (mLooper == null) {throw new RuntimeException("Can't create handler inside thread " + Thread.currentThread()+ " that has not called Looper.prepare()");}// 使用Looper中的MessageQueuemQueue = mLooper.mQueue;mCallback = callback;mAsynchronous = async;
}@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {mLooper = looper;mQueue = looper.mQueue;mCallback = callback;mAsynchronous = async;
}

调用Handler的sendMessage,到Handler处理(handleMessage)这个Message。Handler会将这个Message,入队到绑定的Looper的MessageQueue(消息队列中)。

public final boolean sendMessage(@NonNull Message msg) {// 没有延时 return sendMessageDelayed(msg, 0);
}public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {MessageQueue queue = mQueue;if (queue == null) {RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");Log.w("Looper", e.getMessage(), e);return false;}return enqueueMessage(queue, msg, uptimeMillis);
}private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) {msg.target = this;// 记录一下UIDmsg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {msg.setAsynchronous(true);}// 消息入队MessageQueuereturn queue.enqueueMessage(msg, uptimeMillis);
}

Looper从MessageQueue中依次取出Message,并告知Handler的handleMessage处理消息(想要看懂looper,涉及到其Native实现,这里不分析,可自行了解)

Looper

Looper类基于epoll机制,提供了一套事件驱动机制。Java层的实现在frameworks/base/core/java/android/os/Looper.java,该类中的sMainLooper变量存储了 主线程(或者叫UI线程)对应的Looper,可以通过getMainLooper取得。

public final class Looper {private static final String TAG = "Looper";// sThreadLocal.get() will return null unless you've called prepare().@UnsupportedAppUsagestatic final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();@UnsupportedAppUsageprivate static Looper sMainLooper;  // guarded by Looper.class// 省略public static Looper getMainLooper() {synchronized (Looper.class) {return sMainLooper;}}
}

常见的用法,比如在自定义的线程中。

public class MyThread extends Thread {  private Handler mHandler;  @Override  public void run() {  Looper.prepare(); // 准备Looper  mHandler = new Handler() {  @Override  public void handleMessage(Message msg) {  // 处理消息  }  }  };  Looper.loop(); // 开始循环,等待消息  }
}

Looper的实现这里就不分析了,路径在**/frameworks/base/core/java/android/os/Looper.java**,可自行了解(建议先掌握epoll)

Thread

Android Thread类提供线程功能,其定义在 libcore/ojluni/src/main/java/java/lang/Thread.java

public
class Thread implements Runnable {public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}
}

调用start方法,可以启动线程,比如上面定义的MyThread类。

MyThread thr = new MyThread();
thr.start();

其提供了一些方法,用于控制线程,比如

  • sleep: 让线程等待一段时间
  • jion:等待线程退出(或者叫执行完成)
  • interrupt:打断线程。

注意:Thread和Looper是两个事情,其关系是一对一。 Thread就是常规意义上的线程,程序代码最小的运行单位(先不考虑协程),Looper是一套基于消息(事件)的驱动机制。

Runnable是一个接口类,规定了Run这个方法。MessageQueue是一个消息队列。这个类功能比较单一。其源码路径如下,感兴趣的可自行了解。

  • /frameworks/base/core/java/android/os/MessageQueue.java
  • /libcore/ojluni/src/main/java/java/lang/Runnable.java

再贴一遍类图,加深理解。
在这里插入图片描述

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

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

相关文章

最少按键次数

题目描述 给你一个字符串 s&#xff0c;由小写英文字母组成。 电话键盘上的按键与 不同 小写英文字母集合相映射&#xff0c;可以通过按压按键来组成单词。例如&#xff0c;按键 2 对应 ["a","b","c"]&#xff0c;我们需要按一次键来输入 &quo…

【javaWeb 原理篇】底层实现原理(快速学习配置原理,Bean管理)

Spring底层 配置优先级Bean管理获取beanBean的作用域第三方Bean SpringBoot原理起步依赖自动配置自动配置的原理自定义starter 配置优先级 Spring中的配置文件如果配置了相同的内容则根据配置优先级进行配置: application.properties>application.yml>application.yaml …

用Python+OpenCV截取视频中所有含有字幕的画面

1、需求背景 有的视频文件的字幕已经压制到了视频的图像中&#xff0c;不能单独提取出字幕文件。网上的 “提取视频字幕” 网站多为提取视频中的字幕文件&#xff0c;而非识别视频图像中的字幕。少数通过OCR技术识别画面中字幕的工具需要在线运行、运行速度较慢&#xff0c;或…

蓝桥杯练习笔记(十八)

蓝桥杯练习笔记&#xff08;十八&#xff09; 一、用辅助栈来优化递归深度过大的问题 输入示例 0000100010000001101010101001001100000011 0101111001111101110111100000101010011111 1000010000011101010110000000001011010100 0110101010110000000101100100000101001001 0…

QT打包生成.exe可执行文件

QT打包生成.exe可执行文件 程序运行图标如何设置快捷方式显示图标QT打包成可执行文件将可执行文件打包成安装包程序运行图标 如何生成如下图标? 首先将你的图标(ico文件)放入当前工程目录,即含有.pro文件的同级目录 右击项目,选择ADD New,选择Qt Resource File, 这是一个…

吴恩达2022机器学习专项课程(一) 5.7 检测梯度下降是否收敛

问题预览/关键词 什么是梯度下降收敛&#xff1f;哪些方法可以检测梯度下降是否收敛&#xff1f;什么是学习曲线&#xff1f;曲线上升代表什么&#xff1f;什么原因造成的&#xff1f;如何检测梯度下降是否收敛&#xff1f;多少次迭代&#xff0c;梯度下降会收敛&#xff1f;什…

C++:初步接触C++(2)

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习C&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 文章目录 内联函数1.概念2.特性 auto关键字1.auto简介2.auto的使用细则3.auto不能推导的场景 基于范围…

RTThread studio 驱动开发

rtthread 驱动使用的两种情况 rtthread studio 自动生成 由 RT Thread Studio 自动生成&#xff0c;无需修改任何文件或者简单定义几个宏即可直接使用的驱动&#xff0c;如 GPIO&#xff0c;UART&#xff0c;I2C&#xff0c;SPI&#xff0c;SDIO 和 ETH 等。 使用 RT-Thread S…

如何定位和优化程序CPU、内存等性能之巅

如何定位和优化程序CPU、内存等性能之巅 摘要 性能优化指在不影响系统运行正确性的前提下&#xff0c;使之运行得更快&#xff0c;完成特定功能所需的时间更短&#xff0c;或拥有更强大的服务能力。本文将介绍性能优化的基本概念以及如何定位和优化程序中的CPU、内存和IO瓶颈…

信息泄露漏洞的JS整改方案

引言 &#x1f6e1;️ 日常工作中&#xff0c;我们经常会面临线上环境被第三方安全厂商扫描出JS信息泄露漏洞的情况&#xff0c;这给我们的系统安全带来了潜在威胁。但幸运的是&#xff0c;对于这类漏洞的整改并不复杂。本文将介绍几种可行的整改方法&#xff0c;以及其中一种…

指挥中心控制台厂家定制控制台技术规范全方位指南

指挥中心控制台作为现代化管理的重要组成部分&#xff0c;在整个企业的运行中起着重要作用&#xff0c;为了保证指挥中心的正常运行&#xff0c;控制台的定制不可缺少&#xff0c;那么指挥中心控制台厂家定制控制台技术规范是什么? 1. 结构性能规范&#xff1a;控制台需采用优…

kmeans聚类sklearn实现(Python实验)

Kmeans毫无疑问&#xff0c;好用又“便宜”的算法&#xff0c;经常在很多轻量化场景中实现。所谓的“聚类”&#xff08;Clustering&#xff09;&#xff0c;就是通过欧氏距离找哪些点构成一个簇。假设我们空间中有一堆点&#xff0c;通过肉眼大概可以看出有两簇&#xff0c;思…

jmeter压测websocket协议

一、jmeter 安装websocket插件 1、选项--插件管理 2、搜索WebSocket Samplers by Peter Doornbosch插件 进行安装 3、 重启 jmeter 二、jmeter压测websocket协议实战 2.1、以网站为例&#xff1a; websocket在线测试 1、断开连接 2、打开F12&#xff0c;查看WS数据 3、…

DragonIM龙通讯

前言 龙通讯是一款C/S架构的即时通讯软件&#xff0c;实现了用户注册、登录、好友私聊、群聊&#xff08;文字、表情、文件&#xff09;&#xff0c;群文件上传/下载&#xff0c;群公告&#xff0c;朋友圈&#xff08;可点赞和评论&#xff09;&#xff0c;AI聊天&#xff0c;…

剪切助手-高颜值的跨平台剪切板工具

高颜值的跨平台剪切板工具来了&#xff01;&#xff01; http://t.csdnimg.cn/xKB3B 出于我的一些日常使用需求以及在对比了其他剪切板软件后&#xff0c;我决定做一个跨平台的高颜值剪切板工具《剪切助手》&#xff01; 废话不多说&#xff0c;你可以来这里 下载体验 它&…

day76 jquery

知识点: 1 在HTML中引入jQuery 2 jQuery中就绪函数 3 jQuery中选择器 4 使用jQuery获取表单元素的值 及标签中间的内容 5 jQuery中获取标签属性 6 jQuery设置和获取标签样式 ----------------------------------- 一 在HTML中引入jQuery 1/*! jQuery…

RFID涉密载体柜 RFID智能文件柜系统

涉密载体管控RFID智能柜&#xff08;载体柜DW-G101R&#xff09;通过对涉密物资、设备进行RFID唯一标识并放置于RFID设备涉密物资柜柜体&#xff0c;通过定位每台设备每件涉密物资的位置&#xff0c;实现涉密物资审批、自助借还、防盗等出入库全流程自动化管理。主要管理对象移…

redis 集群模式(redis cluster)介绍

目录 一 redis cluster 相关定义 1&#xff0c; redis cluster 是什么 2&#xff0c;redis 集群的组成 3&#xff0c;集群的作用 4&#xff0c;集群架构图 二 Redis集群的数据分片 1&#xff0c;哈希槽是什么 2&#xff0c;哈希槽如何排布 3&#xff0c;Redis集…

五边形信息图表绘制方法

五边形信息图表绘制方法 在网络科技发展进步的当下&#xff0c;原来一些传统的统计图表都有了进一步的创新。以前企业的PPT都依赖微软的各应用软件来制作图表&#xff0c;现时企业的PPT展示的图表应用不再满足于原来的图表绘制方法&#xff0c;进而使用一些第三方应用软件来制作…

Linux_进程的优先级环境变量上下文切换优先级队列

文章目录 一、进程的优先级二、进程的四个重要概念三、上下文切换四、环境变量查看当前shell环境下的环境变量与内容 五、Linux2.6内核进程调度队列一个CPU拥有一个runqueue优先级活动队列过期队列active指针和expired指针 一、进程的优先级 什么是优先级&#xff1f; 指定一个…