Looper,Message,Handler

Handler、Message、MessageQueue、Looper协作简析 Handler、Message、MessageQueue、Looper工作过程简析。 阅读详情

Looper负责的创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler。

1、Looper

Looper主要是prepare()和loop()两个方法。
首先看prepare()方法:
public static final void prepare() {  
        if (sThreadLocal.get() != null) {  
            throw new RuntimeException("Only one Looper may be created per thread");  
        }  
        sThreadLocal.set(new Looper(true));  
}
sThreadLocal是一个ThreadLocal对象,可以在一个线程中存储变量。可以看到,在第5行,将一个Looper的实例放入了ThreadLocal,并且2-4行判断了sThreadLocal是否为null,否则抛出异常。这也就说明了Looper.prepare()方法不能被调用两次,同时也保证了一个线程中只有一个Looper实例。
下面看Looper的构造方法:
private Looper(boolean quitAllowed) {  
        mQueue = new MessageQueue(quitAllowed);  
        mRun = true;  
        mThread = Thread.currentThread();  
} 
在构造方法中,创建了一个MessageQueue(消息队列)。
然后我们看loop()方法:
public static void loop() {  
        final Looper me = myLooper();  
        if (me == null) {  
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");  
        }  
        final MessageQueue queue = me.mQueue;  
  
        // 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();  
  
        for (;;) {  
            Message msg = queue.next(); // might block  
            if (msg == null) {  
                // No message indicates that the message queue is quitting.  
                return;  
            }  
  
            // This must be in a local variable, in case a UI event sets the logger  
            Printer logging = me.mLogging;  
            if (logging != null) {  
                logging.println(">>>>> Dispatching to " + msg.target + " " +  
                        msg.callback + ": " + msg.what);  
            }  
  
            msg.target.dispatchMessage(msg);  
  
            if (logging != null) {  
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);  
            }  
  
            // Make sure that during the course of dispatching the  
            // identity of the thread wasn't corrupted.  
            final long newIdent = Binder.clearCallingIdentity();  
            if (ident != newIdent) {  
                Log.wtf(TAG, "Thread identity changed from 0x"  
                        + Long.toHexString(ident) + " to 0x"  
                        + Long.toHexString(newIdent) + " while dispatching to "  
                        + msg.target.getClass().getName() + " "  
                        + msg.callback + " what=" + msg.what);  
            }
  
            msg.recycle();  
        }  
} 
第2行:
public static Looper myLooper() {
return sThreadLocal.get();
}
方法直接返回了sThreadLocal存储的Looper实例,如果me为null则抛出异常,也就是说looper方法必须在prepare方法之后运行。
第6行:拿到该looper实例中的mQueue(消息队列)
13到45行:进入了无限循环。
14行:取出一条消息,如果没有消息则阻塞。
27行:使用调用 msg.target.dispatchMessage(msg);把消息交给msg的target的dispatchMessage方法去处理。Msg的target是什么呢?其实就是handler对象,下面会进行分析。
44行:释放消息占据的资源。
Looper主要作用:
1、 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
2、 loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。

2、Handler

首先看一下Handler的构造函数:

public Handler() {  
        this(null, false);  
}  
public Handler(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());  
            }  
        }  
  
        mLooper = Looper.myLooper();  
        if (mLooper == null) {  
            throw new RuntimeException(  
                "Can't create handler inside thread that has not called Looper.prepare()");  
        }  
        mQueue = mLooper.mQueue;  
        mCallback = callback;  
        mAsynchronous = async;  
    }
首先通过Looper.myLooper()获取了当前线程保存的Looper实例,然后又获取了这个Looper实例中保存的MessageQueue(消息队列),这样就保证了handler的实例与我们Looper实例中MessageQueue关联上了。

再看sendMessage方法:

public final boolean sendMessage(Message msg)  
 {  
     return sendMessageDelayed(msg, 0);  
 }  
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {  
     Message msg = Message.obtain();  
     msg.what = what;  
     return sendMessageDelayed(msg, delayMillis);  
 } 
public final boolean sendMessageDelayed(Message msg, long delayMillis)  
   {  
       if (delayMillis < 0) {  
           delayMillis = 0;  
       }  
       return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);  
   }
public boolean sendMessageAtTime(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);  
   }
最后定位到调用了sendMessageAtTime,在此方法内部获取MessageQueue然后调用了enqueueMessage方法,我们再来看看此方法:

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {  
       msg.target = this;  
       if (mAsynchronous) {  
           msg.setAsynchronous(true);  
       }  
       return queue.enqueueMessage(msg, uptimeMillis);  
enqueueMessage中首先为meg.target赋值为this,也就是把当前的handler作为msg的target属性。最终会调用queue的enqueueMessage的方法,也就是说handler发出的消息,最终会保存到消息队列中去。

下面我们再看一看回调的dispathMessage方法:

public void dispatchMessage(Message msg) {  
        if (msg.callback != null) {  
            handleCallback(msg);  
        } else {  
            if (mCallback != null) {  
                if (mCallback.handleMessage(msg)) {  
                    return;  
                }  
            }  
            handleMessage(msg);  
        }  
    }

再看一下这里调用的handleMessge方法:

public void handleMessage(Message msg) {  
} 

可以看到这是一个空方法,为什么呢,因为消息的最终回调是由我们控制的,我们在创建handler的时候都是复写handleMessage方法,然后根据msg.what进行消息处理。










Handler Looper Message原理浅析 Handler Looper MessageQueue 原理浅析 说到Andorid线程间通信最常见的就是Handler,Handler的原理是个大厂面试必问,可见其重要程度。本文在这里从源码角度浅析一下Handler,Looper和MessageQueue 1.从Looper开始 首先我们知道,Looper从字面理解就是轮子的意思。 Looper的源码很少,区区不到300行且大半都是注释。我们直接上代码: private Looper(boolean quitAllowed) { mQueue = 阅读详情

相关推荐

Android Framework学习七:Handler、Looper、Message

文章摘要: 本文介绍了Android中的消息处理机制,核心组件包括Looper、MessageQueue、Handler和Message。Looper作为消息循环的核心,通过Looper.prepareMainLooper()和Looper.loop()启动,确保每个线程拥有独立的Looper对象。MessageQueue是消息队列,以链表形式存储Message。Handler负责发送和处理消息,Message则携带消息内容和目标Handler的引用。Looper.loop()通过循环调用loopOnce(

zmlovelx(帅得不敢出门 程序员群31843264) 1626

Handler Looper Message学习

Android消息机制:Handler、Looper与MessageQueue 摘要:Android采用事件驱动架构,Handler是其核心消息处理工具,配合Looper和MessageQueue实现线程间通信。主线程默认包含一个Looper,通过无限循环处理消息队列中的任务;子线程需手动创建Looper。Handler负责将Message/Runnable投递到关联线程的MessageQueue,并按时间排序执行。创建流程涉及Looper初始化、Native层MessageQueue构建及epoll事件监

c025200的博客 797

Handler通信机制Message,MessageQueue,Handler,Looper讲解及常见面试问题

1.Handler机制常见问题 1)Handler机制基本流程; 2)Handler机制都处理哪些类型消息; 3)Handler发送和处理消息的方式有哪些种? 4)Looper的loop下for循环为什么不会导致ANR? 5)处理消息的先后顺序如何控制? 6)Looper如何主线程绑定,在其他线程如何使用Looper? 7)Message分几种类型,同步和异步? 8)Handler设计思路是什么? ...

Tiger的专栏 1069

Handler、Looper、message进阶知识

在高并发场景中,可能需要消息在特定时间内处理完毕,否则即为过期。可清除指定消息。// 移除所有未处理的消息Handler、Looper和Message的高阶用法提升了Android多线程开发的灵活性。在实际使用中,需要对内存管理和生命周期有深刻理解,合理运用这些特性,避免常见错误,确保应用高性能和稳定性。

执剑人 1052

Android之Handler、Message、MessageQueue、Looper详解

Android之Handler、Message、MessageQueue、Looper详解

是阿超 3527

环境科研人必备:手把手教你用EPISuite 4.1批量预测化合物毒性(附ECOSAR实战)

本文详细介绍了EPISuite 4.1在环境毒理学研究中的应用,重点解析了ECOSAR模块的化合物毒性预测技术。通过批量处理实战和科研案例,帮助环境科研人员快速评估化学物质对水生生态系统的风险,提升工作效率。文章还涵盖了EPISuite核心模块的功能分类及ECOSAR模型的技术原理与算法特点。

weixin_28738165的博客 543

Looper、Message和Handler的关系

Handler、Loop和Message 的关系 Looper中有一个Message队列,里面存储的是一个个待处理的Message;Message中有一个Handler,这个Handler是用来处理Message的。 Message Meaasge是Handler接收和处理的消息对象;MessageQueue是消息队列,采用先进先出的方式来管理Message。 Message类

志在四方 998

图解B树的原理及操作

本文主要参考:https://blog.youkuaiyun.com/shenchaohao12321/article/details/83243314 1. B树 1.1 B树的定义 B树也称B-树,它是一颗多路平衡查找树。我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数。当m取2时,就是我们常见的二叉搜索树。 一颗m阶的B树定义如下: 1)每个结点最多有m-1个关键字。 2)根结点最少可以只有1个关键字。 3)非根结点至少有Math.ceil(m/2)-

jinking01的专栏 3万+

Handler Looper Message 关系是什么?

分析 Handler 首先我们来分析分析一下 Handler 的用法,我们知道,要创建一个 Handler 对象非常的简单明了,直接进行 new 一个对象即可,但是你有没有想过,这里会隐藏着什么注意点呢。现在可以试着写一下下面的一小段代码,然后自己运行看看: public class MainActivity extends ActionBarActivity { private Handler mHandler0; private Handler mHandler1; .

陈立的博客 809

跨境TRS投资操作指南与系统解决方案

3 点击【申请 TRS 账户】,查看风险披露,录入账户参数、确定录入的参数信息,进行身份验证,输入验证码,TRS 账户开户申请已提交,后台对已提交的 TRS 开户申请进行审核,审核成功后,短信邮箱提醒,进行登录;2.点击【申请TRS账户】,查看风险披露,录入账户参数、确定录入的参数信息,进行身份验证,输入验证码,TRS账户开户申请已提交,后台对已提交的TRS开户申请进行审核,审核成功后,短信邮箱提醒,进行登录;4)更广泛的投资选择:相比A股通,TRS可以交易更多的A股标的,提供了更广泛的投资选择。

2401_85487119的博客 2852

Zynq UltraScale+ RFSoC实战:用XCZU49DR开发板实现雷达信号处理全流程

本文详细介绍了如何利用Xilinx Zynq UltraScale+ RFSoC系列中的XCZU49DR开发板,高效实现雷达信号处理全流程。文章深入剖析了该芯片集成的射频直采ADC/DAC、可编程逻辑与Arm多核处理器的异构计算优势,并通过实战案例展示了从环境搭建、硬件链路设计到软件优化的完整开发路径,为相控阵雷达等高性能应用提供了单芯片解决方案。

weixin_29291863的博客 578

十分钟了解Android Handler、Looper、Message

Handler和Message可以通过Looper在不同线程间传递数据。主线程默认有Looper,子线程需手动创建。使用Handler可以简化线程间通信和UI更新的逻辑。

执剑人 894

如何选择StandardScaler、MinMaxScaler和RobustScaler做标准化的对比解释和示例代码

选择合适的标准化方法取决于数据的特点和需求。如果数据分布接近正态分布且无异常值,可以使用。如果需要将数据映射到特定范围内并保持相对关系,可以使用。如果数据中存在异常值或离群点,可以使用进行鲁棒标准化。在分类、聚类算法中,需要使用距离来度量相似性的时候、或者使用PCA技术进行降维的时候,StandardScaler表现更好(避免不同量纲对方差、协方差计算的影响);在不涉及距离度量、协方差、数据不符合正态分布、异常值较少的时候,可使用MinMaxScaler。

qq_36001281的博客 4940

Handler Looper MessageQueue Message

工作流程: Handler 将Message 发送至MessageQueue 消息队列,然后Looper从MessqgeQueue中取出消息发送给Handler, Handler在处理Message 对象和Runnable对象。 主线程创建一个Looper looper.prepare() public static final void prepare() { if (sThreadL...

qq_35957672的博客 239

Android Google 支付接入

1. 从 2023 年 8 月 2 日起,所有新应用都必须使用结算库版本 5 或更高版本。自 2023 年 11 月 1 日起,现有应用的所有新版本都必须使用结算库版本 5 或更高版本。 2. 如果您的应用以 Android 14 或更高版本为目标平台,您必须更新到 PBL 5.2.1 或 PBL 6.0.1 或更高版本。

帅次的博客 9404

如何解决群晖Docker注册表查询失败/无法拉取镜像等问题

如何解决群晖Docker注册表查询失败/无法拉取镜像等问题

XiaoqiangClub的博客 1万+

Message Handler Looper

一、Message Message创建方式有两种,一种是new Message(),开销较大,另外一种是Message.obtain(), 使用回收但是没有被释放的message对象,减少开销,有点类似Adapter中的ConvertView与ViewHolder,一般使用Message msg = Handler.obtain(),事实上也是调用Message.Obtain(). Ha

mouttz的专栏 682

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Handler Looper Message MessageQueue源码学习

原理图 Message int what(标识ID) int arg1 保存int数据 int arg2 保存int数据 Object obj 保存任意数据 long when 记录应该处理的时间 Handler target 每一个Message都保存一个用来处理此Message的Handler(发送消息的Handler) Runnable callback ...

杰锅锅dev 6072

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Handler、Looper、Message之间关系

Handler、Looper(轮循器)、MessageQueue(消息队列)、Message(消息)工作原理----面试问题 与Handler一起工作的几个组件: Message:Handler接收和处理的消息对象。 MessageQueue:消息队列,他采用先进先出的方式来管理Message。Handler发送消息时先把消息发送到消息队列中。 Looper:每个线...

baidu_39503346的博客 716

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

一张图让你明白Handler、Message、Looper消息机制

转载请注明出自flowsky37的博客,尊重他人辛苦劳动!在android开发中,Handler太熟悉了,处处可见。确实挺好用的。它可以轻松的将任务切换到Handler所在的线程中去执行。如下面代码://发送message MyHandler myHandler = new MyHandler(this); //业务逻辑 ... Message mess

flowsky37的专栏 1564

【Android】Handler Looper Message简介

Looper:是消息循环监听器,一个线程(包括UI线程)和Handler是一对多的关系,也就是在线程中使用handler,必须要有Looper。 Handler:发送消息和处理消息 Message:一个消息对象 MessageQueue:相当于消息池,Looper中loop()会从MessageQueue.next()取出Message对象。 先来看下,Handler、Message、Looper的使用: 1 UI线程下使用Handler: 输出的log: 这里的handler是在主线程里面工作。 2

sinat_36955332的博客 310

Android 总结:Message,MessageQueue,Looper,Handler 消息机制

每一个Looper对象和一个线程关联,通过调用可以获得当前线程的Looper对象。Looper从MessageQueue中取出Message然后,交由Handler的进行处理。处理完成后,调用将其放入MessagePool中。

zxfbhxgnc的博客 636

Andrid中的Looper,Handler,Message研究

外链图片转存中…(img-dCQTMZUU-1710756468580)][外链图片转存中…(img-HReZJAYm-1710756468580)][外链图片转存中…(img-7N6fY6DA-1710756468580)][外链图片转存中…(img-tHORf0Qh-1710756468581)]

m0_60388216的博客 939

Handler、Looper、MessageQueue、Message解析

Handler、Looper、MessageQueue、Message解析Handler相关源码逻辑梳理Handler用法Message合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章...

archie_7的博客 471

Handler、Looper、Message的理解

浅谈Handler、Looper、Message

巨石强森小童鞋的博客 482
上一篇: JavaScript中判断对象类型的几种方法
下一篇: HTTP协议头详解
hunter800421
博客等级 码龄22年 60粉丝 97原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值