Android Framework学习七:Handler、Looper、Message
文章目录
- 简介
- Looper
- Message
- MessageQueue
- Handler
- Framework学习系列文章
简介
Looper当做一台传送装置,MessageQueue是传送带,传送带上放的是Message,Handler用于发送Message分发与接收处理。
Looper
frameworks/base/core/java/android/app/ActivityThread.java
ActivityThread.main是APP的入口函数,先调用Looper.prepareMainLooper创建Looper,再调用Looper.loop让它跑起来。
public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}Looper.loop();}
frameworks/base/core/java/android/os/Looper.java
public final class 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.classprivate static Observer sObserver;@UnsupportedAppUsagefinal MessageQueue mQueue;final Thread mThread;...
}
ThreadLocal 是 Android 和 Java 中一个用于实现线程隔离的工具类,它能让每个使用该变量的线程都拥有独立的副本,线程间对该变量的操作互不影响。
APP入口函数会调用prepareMainLooper->prepare, 会新建一个Looper对象给
sThreadLocal,保证线程有且拥有一个只有自己能用的Looper对象。
sMainLooper通过myLooper函数赋值,其实就是sThreadLocal中的Looper对象
/*** Return the Looper object associated with the current thread. Returns* null if the calling thread is not associated with a Looper.*/public static @Nullable Looper myLooper() {return sThreadLocal.get();}
Looper.loop
loop()其实是在一个死循环中,不断执行loopOnce函数
/*** Run the message queue in this thread. Be sure to call* {@link #quit()} to end the loop.*/@SuppressWarnings("AndroidFrameworkBinderIdentity")public static void loop() {final Looper me = myLooper();if (me == null) {throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");}if (me.mInLoop) {Slog.w(TAG, "Loop again would have the queued messages be executed"+ " before this one completed.");}me.mInLoop = true;// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.Binder.clearCallingIdentity();final long ident = Binder.clearCallingIdentity();// Allow overriding a threshold with a system prop. e.g.// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'final int thresholdOverride =SystemProperties.getInt("persist.log.looper."+ Process.myUid() + "."+ Thread.currentThread().getName()+ ".slow", 0);me.mSlowDeliveryDetected = false;for (;;) {if (!loopOnce(me, ident, thresholdOverride)) {return;}}}
在loopOnce中会调用msg.target.dispatchMessage(msg)分发消息
private static boolean loopOnce(final Looper me,final long ident, final int thresholdOverride) {....Message msg = me.mQueue.next(); // might block....try {msg.target.dispatchMessage(msg);if (observer != null) {observer.messageDispatched(token, msg);}dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;} catch (Exception exception) {if (observer != null) {observer.dispatchingThrewException(token, msg, exception);}throw exception;} finally {ThreadLocalWorkSource.restore(origWorkSource);if (traceTag != 0) {Trace.traceEnd(traceTag);}}.... }
这个msg.target的target其实是Handler对象,msg.target.dispatchMessage调用的是Handler.dispatchMessage
Message
这个target就是Handler, 也就是Message中会有Handler的引用,
frameworks/base/core/java/android/os/Message.java
/*** Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>* members.* @param h The <em>target</em> value to set.* @param what The <em>what</em> value to set.* @param obj The <em>object</em> method to set.* @return A Message object from the global pool.*/public static Message obtain(Handler h, int what, Object obj) {Message m = obtain();m.target = h;m.what = what;m.obj = obj;return m;}
MessageQueue
MessageQueue是由链表组成的,用于存放Message
MessageQueue主要函数
Handler
发送Message时sendMessage最终都会调用enqueueMessage
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}/*** Enqueue a message into the message queue after all pending messages* before the absolute time (in milliseconds) <var>uptimeMillis</var>.* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>* Time spent in deep sleep will add an additional delay to execution.* You will receive it in {@link #handleMessage}, in the thread attached* to this handler.** @param uptimeMillis The absolute time at which the message should be* delivered, using the* {@link android.os.SystemClock#uptimeMillis} time-base.** @return Returns true if the message was successfully placed in to the* message queue. Returns false on failure, usually because the* looper processing the message queue is exiting. Note that a* result of true does not mean the message will be processed -- if* the looper is quit before the delivery time of the message* occurs then the message will be dropped.*/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);}
会调用queue.enqueueMessage,这个queue其实是MessageQueue,把Message放入MessageQueue
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) {msg.target = this;msg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}
接收到消息后处理时
dispatchMessage会调用到handleMessage,就会进入Message的处理部分
frameworks/base/core/java/android/os/Handler.java
/*** Callback interface you can use when instantiating a Handler to avoid* having to implement your own subclass of Handler.*/public interface Callback {/*** @param msg A {@link android.os.Message Message} object* @return True if no further handling is desired*/boolean handleMessage(@NonNull Message msg);}/*** Subclasses must implement this to receive messages.*/public void handleMessage(@NonNull Message msg) {}/*** Handle system messages here.*/public void dispatchMessage(@NonNull Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}
Framework学习系列文章
Android Framework学习一:系统框架、启动过程
Android Framework学习二:Activity创建及View绘制流程
Android Framework学习三:zygote
Android Framework学习四:APP速度优化
Android Framework学习五:APP启动过程原理及速度优化
Android Framework学习六:Binder原理
Android Framework学习七:Handler、Looper、Message
作者:帅得不敢出门
相关文章:

Android Framework学习七:Handler、Looper、Message
文章目录 简介LooperMessageMessageQueueHandlerFramework学习系列文章 简介 Looper当做一台传送装置,MessageQueue是传送带,传送带上放的是Message,Handler用于发送Message分发与接收处理。 Looper frameworks/base/core/java/android/app…...

MyBatis:简化数据库操作的持久层框架
1、什么是Mybatis? MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由 apachesoftwarefoundation 迁移到了google code,由谷歌托管,并且改名为MyBatis 。 2013年11月迁移到Github。 iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框…...

【001】RenPy打包安卓apk 流程源码级别分析
1. 入口在下图 2. SDK版本及代码入口 (renpy-8.3.7-sdk) 由于SDK一直在升级,本文采用 标题中的版本进行分析,整体逻辑变化不太大。 实际执行逻辑是调用的rapt 2.1 点击按钮实际执行逻辑 def AndroidIfState(state, needed, acti…...

物理信息神经网络(PINNs)在悬臂梁分析中的应用研究
一、引言 物理信息神经网络(Physics-Informed Neural Networks, PINNs)是近年来兴起的一种结合深度学习与传统物理建模的创新方法。本文将探讨PINNs在悬臂梁力学分析中的应用,展示如何利用这一技术解决工程力学中的经典问题。 二、PINNs基本原理 PINNs的核心思想是…...

论文浅尝 | HOLMES:面向大语言模型多跳问答的超关系知识图谱方法(ACL2024)
笔记整理:李晓彤,浙江大学硕士,研究方向为大语言模型 论文链接:https://arxiv.org/pdf/2406.06027 发表会议:ACL 2024 1. 动机 多跳问答(Multi-Hop Question Answering, MHQA)技术近年来在自然语…...
npm、pnpm、yarn 各自优劣深度剖析
在前端开发领域,包管理工具是开发者的得力助手,它们负责处理项目中的依赖安装、更新与管理。npm、pnpm、yarn 是目前最主流的三款包管理工具,它们在功能上有诸多相似之处,但在实际使用中又各有优劣。本文将结合包管理工具常见问题…...

jenkins使用Send build artifacts over SSH发布jar包目录配置
本测试用ruoyi-plus的代码。 1 [GitLab 自动触发 Jenkins 构建_jenkins构建触发器没有build when a change is pushed to git-CSDN博客](https://blog.csdn.net/wangyiyungw/article/details/81776972) 2 [jenkins使用Send build artifacts over SSH遇到的坑-CSDN博客](https…...

uni-app小程序登录后…
前情 最近新接了一个全新项目,是类似商城的小程序项目,我负责从0开始搭建小程序,我选用的技术栈是uni-app技术栈,其中就有一个用户登录功能,小程序部分页面是需要登录才可以查看的,对于未登录的用户需要引…...

【深度学习基础】从感知机到多层神经网络:模型原理、结构与计算过程全解析
【深度学习基础】从感知机到多层神经网络:模型原理、结构与计算过程全解析 1. 引言 神经网络的重要性: 作为人工智能的核心技术之一,神经网络通过模拟人脑神经元的工作机制,成为解决复杂模式识别、预测和决策任务的利器。从图像分…...
【Leetcode】取余/2的幂次方
给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。 示例 1: 输入: num 38 输出: 2 解释: 各位相加的过程为: 38 --> 3 8 --> 11 11 --> 1 1 --> 2 由于 2 是一位数,所以返回 2。 …...

解决Power BI Desktop导入Excel数据第一行不是列标题问题
选中第一行不是列标题的表→鼠标右键→选择编辑查询→进入Power Query界面→点击“将第一行用作标题”→点击左边的“关闭并应用” 第一行就提升为标题了...

springboot3.x只需两步快速整合nacos作配置中心
一、下载依赖 我在网上找了各种资料,都是要先确定springcloud版本,实际操作却可能由于版本或者镜像或者maven等问题报红,出现各种情况。 实际只需要指定特定版本号就行,添加下面两个依赖 <dependency><groupId>com.…...
python如何遍历postgresql所有的用户表
要遍历PostgreSQL数据库中的所有用户表,可以按照以下步骤操作: 安装必要依赖库 pip install psycopg2-binary使用标准SQL查询方案(推荐) import psycopg2def list_user_tables():try:conn psycopg2.connect(host"your_ho…...
c/c++的opencv高斯模糊
深入探索图像高斯模糊:原理、C/C实现与OpenCV应用 在图像处理的众多技术中,模糊(或平滑)是最为基础且不可或缺的一环。它广泛应用于降噪、图像预处理、特征提取前的平滑以及计算机图形学中的各种视觉效果。在高斯模糊(…...

<uniapp><vuex><状态管理>在uniapp中,如何使用vuex实现数据共享与传递?
前言 本专栏是基于uniapp实现手机端各种小功能的程序,并且基于各种通讯协议如http、websocekt等,实现手机端作为客户端(或者是手持机、PDA等),与服务端进行数据通讯的实例开发。 发文平台 CSDN 环境配置 系统&…...
Java Stream流:高效数据处理的现代解决方案
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、Stream流概述 Java 8引入的Stream API为集合操作带来了革命性改进,它结合Lambda表达式实现了声明式编程风格,支持并行处理&#…...

数据湖和数据仓库的区别
在当今数据驱动的时代,企业需要处理和存储海量数据。数据湖与数据仓库作为两种主要的数据存储解决方案,各自有其独特的优势与适用场景。本文将客观详细地介绍数据湖与数据仓库的基本概念、核心区别、应用场景以及未来发展趋势,帮助读者更好地…...

【论文阅读 | AAAI 2025 | FD2-Net:用于红外 - 可见光目标检测的频率驱动特征分解网络】
论文阅读 | AAAI 2025 | FD2-Net:用于红外 - 可见光目标检测的频率驱动特征分解网络 1.摘要&&引言2. 方法2.1总体架构2.2特征分解编码器2.3多模态重建机制2.4训练损失 3.实验3.1实验设置3.2主要结果3.3消融研究 4.结论 题目:FD2-Net: Frequency-…...
前端取经路——量子UI:响应式交互新范式
嘿,老铁们好啊!我是老十三,一枚普通的前端切图仔(不,开玩笑的,我是正经开发)。最近前端技术简直跟坐火箭一样,飞速发展!今天我就跟大家唠唠从状态管理到实时渲染…...
计算机视觉与深度学习 | matlab实现EMD-VMD-LSTM时间序列预测(完整源码和数据)
EMD-VMD-LSTM 一、完整代码实现二、代码结构说明三、关键参数说明四、注意事项五、典型输出示例以下是使用MATLAB实现EMD-VMD-LSTM时间序列预测的完整代码,包含数据生成、经验模态分解(EMD)、变分模态分解(VMD)、LSTM模型构建与预测分析。代码通过对比实验验证分解策略的有…...

济南国网数字化培训班学习笔记-第三组-1-电力通信传输网认知
电力通信传输网认知 电力通信基本情况 传输介质 传输介质类型(导引与非导引) 导引传输介质,如电缆、光纤; 非导引传输介质,如无线电波; 传输介质的选择影响信号传输质量 信号传输模式(单工…...

OAT 初始化时出错?问题可能出在 PAM 配置上|OceanBase 故障排查实践
本文作者:爱可生数据库工程师,任仲禹,擅长故障分析和性能优化。 背景 某客户在使用 OAT 初始化OceanBase 服务器的过程中,进行到 precheck 步骤时,遇到了如下报错信息: ERROR - check current session ha…...

1-机器学习的基本概念
文章目录 一、机器学习的步骤Step1 - Function with unknownStep2 - Define Loss from Training DataStep3 - Optimization 二、机器学习的改进Q1 - 线性模型有一些缺点Q2 - 重新诠释机器学习的三步Q3 - 机器学习的扩展Q4 - 过拟合问题(Overfitting) 一、…...

Hass-Panel - 开源智能家居控制面板
文章目录 ▎项目介绍:预览图▎主要特性安装部署Docker方式 正式版Home Assistant Addon方式详细安装方式1. Home Assistant 插件安装(推荐)2. Docker 安装命令功能说明 :3. Docker Compose 安装升级说明Docker Compose 版本升级 功…...

Ubuntu搭建NFS服务器的方法
0 工具 Ubuntu 18.041 Ubuntu搭建NFS服务器的方法 在Ubuntu下搭建NFS(网络文件系统)服务器可以让我们像访问本地文件一样访问Ubuntu上的文件,例如可以把开发板的根文件系统放到NFS服务器目录下方便调试。 1.1 安装nfs-kernel-server&#…...

网感驱动下开源AI大模型AI智能名片S2B2C商城小程序源码的实践路径研究
摘要:在数字化浪潮中,网感已成为内容创作者与商业运营者必备的核心能力。本文以开源AI大模型、AI智能名片及S2B2C商城小程序源码为技术载体,通过解析网感培养与用户需求洞察的内在关联,提出"数据驱动-场景适配-价值重构"…...

COMPUTEX 2025 | 广和通5G AI MiFi解决方案助力移动宽带终端迈向AI新未来
随着5G与AI不断融合,稳定高速、智能的移动网络已成为商务、旅行、户外作业等场景的刚需。广和通5G AI MiFi方案凭借领先技术与创新设计,重新定义5G移动网络体验。 广和通5G AI MiFi 方案搭载高通 4nm制程QCM4490平台,融合手机级超低功耗技术…...

防范Java应用中的恶意文件上传:确保服务器的安全性
防范Java应用中的恶意文件上传:确保服务器的安全性 在当今数字化时代,Java 应用无处不在,而文件上传功能作为许多应用的核心组件,却潜藏着巨大的安全隐患。恶意文件上传可能导致服务器被入侵、数据泄露甚至服务瘫痪,因…...

STM32H7时钟树
时钟树分析 STM32H7共有6个外部时钟源,分别是: HSI(高速内部振荡器)时钟:~ 8 MHz、16 MHz、32 MHz 或 64 MHzHSE(高速外部振荡器)时钟:4 MHz 到 48 MHzLSE(低速外部振荡器ÿ…...
git 的 .gitignore 规则文件
# .gitignore 使用注意事项: # 1. 所有的注释只能是独占单行注释,不能在有效代码后注释!否者不生效!比如错误示范: # 实例: MDK/ #忽略MDK目录下所有内容 (跟在有效代码后注释,非法ÿ…...