handler机制原理分析(适合初学者)1.0

任何一个APK都是从framework层的ActivityThread的main()函数中开始执行,接着调用prepareMainLooer()为UI线程创建一个消息队列MessageQueue.并执行Looper.loop().

Handler消息机制的原理是什么了?我们先来写一个程序看看。

首先看new Handler().做了什么

可以看出在new Handler()中获取了Loop,messagequeue,callback,等对象。

接下来看handler.sendEmptyMessage(DATA)做了什么。

通过源码可以看出,handler.sendEmptyMessage(DATA)最后走到了queue.enqueueMessage(msg, uptimeMillis),  queue是消息队列MessageQueue,现在就要知道消息队列的enqueueMessage(msg. UptimeMills)做了些什么,查看源码,这个方法的源码太长,且不易理解,最后通过查看资料可知,这个方法主要是以一种链式的结构将消息msg存放在消息队列messageQueue中,这样我们就知道,原来handler.sendEmptyMessage(DATA)的作用就是将消息msg放到MessageQueue中。

这样就完了,但是我们是如何来不断的获取消息,然后处理消息的了,这里就要用到Looper对象了,首先我们要知道一点,一个线程中存在Looper对象,则必定存在一个MessageQueue对象,并且只存在一个Looper对象和一个MessageQueue对象,线程,Looper,MessageQueue是1:1:1的关系。在android系统中,除了主线程有默认的Looper对象,其它线程默认是没有Looper对象,如果想让我们新创建的线程拥有Looper对象,我们首先要调用Looper.preare(),然后在调用Looper.loop()方法,倘若我们的线程中存在Looper对象,则我们可以通过Looper.myLooper()获取,此外我们还可以通过Looper.getMainLooper()获取当前应用系统中主线程的Looper对象,在这里有一点需要注意的是,假如Looper对象位于主线程中,则二者获取的是同一个对象。

上面我们谈到,只有主线程中才会默认有一个Looper对象,这是为什么了?首先我们要知道,任何一个APK都是从framework层的ActivityThread的main()函数中开始执行,来看看main()中做了什么

上面可以看出,在main中首先调用了Looper.prepareMainLooper();接着new 了一个ActivityTHread 对象,紧接着就是调用Looper.loop,接下来我们看看这几个方法具体干了些什么,首先看看Looper.prepareMainLooper()

首先调用了prepare(false),看看这个方法做了什么

这个方法中有个ThreadLocal对象,调用了这个对象的get,与set方法,那么这个ThreadLocal又是个什么东西了,通过查看资料了解到,ThreadLocal并不是一个thread,而只是thread的一个局部变量,它里面的原理其实很简单,在ThreadLocal中封装了一个Map对象,set(new Looper(quitAllowed))方法中其实就是以当前的线程为键,以new Looper(quitAllowed)对象为值放入map集合中,调用get()方法是,先获取当前线程对象presentthread,再通过presentthread对象从map集合中取出值。接下来就很清楚了,第一次调用sThreadLocal.get()方法时肯定为null,接着就会在ThreadLocal中以主线程对象为键,new 一个Looper对象为值放入Map中,接下来在prepareMainLooper中会执行sMainLooper=myLooper(),看看myLooper中做了什么

这样就很清楚了,myLooper()方法其实就是返回一个Looper对象,也就是我们刚刚在prapare(false)中new的Looper对象,这样Looper.prapareMainLooper()其实就是为主线程创建了一个Looper对象。

接下来我们看看Looper.loop()(都是静态方法可以直接调用)做了什么

最核心的就是上图的4个地方,首先看看

1:获取到Looper对象 Looper = me = myLooper();

2: 获取到消息对象 MessageQueue queue = me.mQueue;

3:获取到下一个消息 Message msg  = queue.next();

4:将消息分发出去 msg.target.dispatchMessage(msg);

大家可以看到3处获取下一个消息实际上是在一个for循环中,并且是一个死循环,就是说不停的从消息队列中抽取消息,只要消息不为空就不会跳出循环,接着就是分发消息了,来看看msg.target.dispatchMessage(msg)做了些什么,这里要指出的是msg.target得到的是一个handler对象,实际上在我们获取消息调用Message message = handler.obtainMessage()时就会为每一个消息设置一个target的,这个target就是调用它的handler,代码如下

接下来就很清楚了,直接看看handler的dispatchMessage(msg)

最后可以看到调用了handleMessage(msg)(这里我只讨论了else里面的情况,剩下的情况大家可以自己去看)

源码中这是一个空方法,一般需要我们去重写这个方法,自己想怎么处理消息就怎么处理。这样似乎就完了,大家是不是有一个疑问,就是我刚刚说的,这一切能顺利的进行下去是因为在3处得到的消息不为空,但是我们知道主线程的Looper.loop()是在ActivityThread的Main方法中调用的,这时消息队列中可没有消息啊,一旦获取到的msg为空,直接return ,for循环就会跳出,方法loop()就这样结束了,这怎么能行了?方法loop()可以结束吗,一旦结束了,那么接下来还有消息怎么办了,谁来从消息队列中抽取消息了,我们可从来没有在主线程中自己亲自调用过Loop()方法,这就需要看看3处Message msg = queue.next()到底做了什么,看msg到底能不能为null,什么时候可以为null。

在next方法中首先就来了一个for循环,和loop()方法中一样,也是个死循环,那么什么时候可以结束这个循环了,看2处当mQuiting为true时就会return null ,这个时候next()方法就会返回一个空值,对应着loop()中就会跳出for的死循环,结束抽取消息,那么这个mQuiting是在什么地方赋值的了?

通过查看源码,可知是在MessageQueue.quit(boolean)中赋值的,也就是说只有当我们调用MesssageQueue.quit(false)时,Loop()方法才会结束,实际上Looper也有一个quit方法,我们来来Looper.quit()做了什么

这样大家就很清楚了吧,实际上mQuiting的初始值是false,接下来代码继续往下走来到3处。首先判断msg!=null,如果不成立则开始下一个循环,成立则来到4处,再次判断msg是否为null,这里肯定是不为null了,前面已经判断过了,接着就是5处的返回msg了,这里返回的msg肯定不为null了,所有在loop()方法中,只要我们不调用Looper.quit(),那么queue.next()就一定不会返回一个null的msg,至此handler机制分析完毕。

最后来张图方便理解

时间: 2024-11-05 17:21:39

handler机制原理分析(适合初学者)1.0的相关文章

Redis 发布/订阅机制原理分析

Redis 通过 PUBLISH. SUBSCRIBE 和 PSUBSCRIBE 等命令实现发布和订阅功能. 这些命令被广泛用于构建即时通信应用,比如网络聊天室(chatroom)和实时广播.实时提醒等. 本文通过分析 Redis 源码里的 pubsub.c 文件,了解发布和订阅机制的底层实现,籍此加深对 Redis 的理解. 订阅.发布和退订 在开始研究源码之前,不妨先来回顾一下几个相关命令的使用方式. PUBLISH 命令用于向给定的频道发送信息,返回值为接收到信息的订阅者数量: redis

Android Handler 机制原理(转)

andriod提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange). 1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列). 2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息.3)

小记--------spark的Master的Application注册机制源码分析及Master的注册机制原理分析

原理图解: Master类位置所在:spark-core_2.11-2.1.0.jar的org.apache.spark.deploy.master下的Master类 //截取了部分代码 //处理Application注册的请求 case RegisterApplication(description, driver) => //如果master的状态是standby,也就是当前这个master,是standby master,不是active master //那么Application来请求

andrjoid中handler机制原理

andriod提供了 Handler 和 Looper 来满足线程间的通信.Handler 先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(Message Exchange). 1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列). 2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的

Handler机制原理

首先说说Handler 使用中隐藏的坑 1.delay的时间过长,导致 activity未被回收内存泄漏以及逻辑错误 可以将Handler携程static静态内部类,或者而降handler中引用的activity位软引用 2.new 了过多的message,导致内存泄漏,应该在处理后remove这些msg 3.Activity finish()后应该remove所有的msg和runable -----------------------------------------------------

android高级---->Handler的原理

andriod提供了Handler来满足线程间的通信,上次在更新UI的时候也提到过Handler的使用,关于Handler的基本使用,参见博客(android基础---->子线程更新UI).今天我们深入Handler的源码,了解一个Handler的内部执行原理. 目录导航 Handler简单说明 ActivityThread的说明 Handler的预备分析 Handler的原理分析 友情链接 Handler简单说明 一. 在Handler的原理说明之前,我们列出相关的重要的类: Message:

Handler机制实例

Handler机制原理推荐看这篇博客:http://blog.csdn.net/jiayi_yao/article/details/51082073 实例,请看本文. AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" pack

【转载】Select函数实现原理分析

Select函数实现原理分析 <原文> select需要驱动程序的支持,驱动程序实现fops内的poll函数.select通过每个设备文件对应的poll函数提供的信息判断当前是否有资源可用(如可读或写),如果有的话则返回可用资源的文件描述符个数,没有的话则睡眠,等待有资源变为可用时再被唤醒继续执行. 下面我们分两个过程来分析select: 1. select的睡眠过程 支持阻塞操作的设备驱动通常会实现一组自身的等待队列如读/写等待队列用于支持上层(用户层)所需的BLOCK(阻塞)或NONBLO

【转载】Android 的 Handler 机制实现原理分析

handler在安卓开发中是必须掌握的技术,但是很多人都是停留在使用阶段.使用起来很简单,就两个步骤,在主线程重写handler的handleMessage( )方法,在工作线程发送消息.但是,有没有人想过这种技术是怎么实现的呢?下面我们一起探讨下. 先上图,让大家好理解下handler机制: handler机制示例图 上面一共出现了几种类,ActivityThread,Handler,MessageQueue,Looper,msg(Message),对这些类作简要介绍: ActivityThr