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

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
作者:帅得不敢出门

http://www.lryc.cn/news/2383611.html

相关文章:

  • MyBatis:简化数据库操作的持久层框架
  • 【001】RenPy打包安卓apk 流程源码级别分析
  • 物理信息神经网络(PINNs)在悬臂梁分析中的应用研究
  • 论文浅尝 | HOLMES:面向大语言模型多跳问答的超关系知识图谱方法(ACL2024)
  • npm、pnpm、yarn 各自优劣深度剖析
  • jenkins使用Send build artifacts over SSH发布jar包目录配置
  • uni-app小程序登录后…
  • 【深度学习基础】从感知机到多层神经网络:模型原理、结构与计算过程全解析
  • 【Leetcode】取余/2的幂次方
  • 解决Power BI Desktop导入Excel数据第一行不是列标题问题
  • springboot3.x只需两步快速整合nacos作配置中心
  • python如何遍历postgresql所有的用户表
  • c/c++的opencv高斯模糊
  • <uniapp><vuex><状态管理>在uniapp中,如何使用vuex实现数据共享与传递?
  • Java Stream流:高效数据处理的现代解决方案
  • 数据湖和数据仓库的区别
  • 【论文阅读 | AAAI 2025 | FD2-Net:用于红外 - 可见光目标检测的频率驱动特征分解网络】
  • 前端取经路——量子UI:响应式交互新范式
  • 计算机视觉与深度学习 | matlab实现EMD-VMD-LSTM时间序列预测(完整源码和数据)
  • 济南国网数字化培训班学习笔记-第三组-1-电力通信传输网认知
  • OAT 初始化时出错?问题可能出在 PAM 配置上|OceanBase 故障排查实践
  • 1-机器学习的基本概念
  • Hass-Panel - 开源智能家居控制面板
  • Ubuntu搭建NFS服务器的方法
  • 网感驱动下开源AI大模型AI智能名片S2B2C商城小程序源码的实践路径研究
  • COMPUTEX 2025 | 广和通5G AI MiFi解决方案助力移动宽带终端迈向AI新未来
  • 防范Java应用中的恶意文件上传:确保服务器的安全性
  • STM32H7时钟树
  • git 的 .gitignore 规则文件
  • 【通用智能体】Serper API 详解:搜索引擎数据获取的核心工具