handler的原理以及底层的实现

来源:互联网 发布:淘宝保存草稿箱找不到 编辑:程序博客网 时间:2024/06/17 04:13

Handler

相信大家对Handler再熟悉不过了,平常使用它的频率也比较高,我们知道它是用来线程间通信的,但是handler是怎么实现通信的,可能就需要我们做进一步的了解,在面试中也是经常会问到的问题,下面我就带着大家跟一跟Handler的源码。 
在跟代码之前我们先对Handler原理做个大致打介绍:

Handler:用来发送消息,处理消息 
Message:消息实体对象,handler通过sendMsg将实体放到消息队列里面 
MessageQueue:存放消息的队列 
Looper:消息轮询器,轮询消息队列的消息然后取出,交给handler处理

Handler源码

进入Handler实现,首先看一下代码行数800行,并不多,注释都有100行,所以Handler的代码相对很少,它的主要方法都有:

这里写图片描述

那么上面打方法我们应该怎么看呢?我们在看源码的时候通常会遇到这个问题,方法那么多,应该从何处看起?不要急,我来交大家一个方法:

首先看代码有多少行,心里大致有个底,然后是构造方法,看看有哪些构造函数,然后浏览一些setter,getter,这些都是一些无关紧要打东西,大致浏览即可,接下来就主要看我们调用的方法,就能找到主线了!

Handler我们经常调用的有:obtain…,sendMsg…,post…remove…new Handler(callback),挨着看就是,首先封装消息打方法obtain…

进入源码我们看obtain都做了些什么操作: 
这里写图片描述

我们可以发现在方法里面走打都是 Message.obtain(),在Message.obtain()封装来对象message,设置target,callback 
这里写图片描述

重点来了,target,callback是Message对象的属性,他们是干嘛的,有什么用,后面我们在说!

接下来看send… 
这里写图片描述

发现最后都会走sendMessageAtTime,在这个方法里面,将msg通过enqueueMessage(queue, msg, uptimeMillis)把消息放在消息队列里面

post…

这里写图片描述 
post里面传来一个Runable,通过getPostMessage(r)构造一个message对象,最终一样的走的是sendMessageAtTime()(sendMessageAtFrontOfQueue)

remove….

这里写图片描述

最后都是走 mQueue.removeMessage….,在方法里面写了个while(true), n.recycleUnchecked() ,从而将消息移除。

Message源码

看完Handler,我们在看看Message.注意两个属性: 
Handler target 
Runnable callback

其他方法看Handler的时候基本已经过了。

MessageQueue,Looper

看到现在,我们的消息已经知道时怎么发送到消息队列里面去了,那么我们现在要关注的是消息是怎么取出来,然后发送给handler的呢?带着问题我们去看,Looper轮训器,在loop()方法里面

这里写图片描述

我们会看到一行代码msg.target.dispatchMessage(msg),取出消息之后,拿到发送消息的Handler对象target,然后调用dispatchMessage()(这里我们可以明白Message为什么要有target属性)

进入dispatchMessage,方法里面有3个分支,这3个分支正式我们使用handler方法对应的分支(send,post,callback): 
这里写图片描述

1.handleCallback(msg):callback(Runnable!=null),我们可以推断Handler的post..调用走这个分支,最后调用run()方法(在这里我们也可以解释handler.post(为什么是在主线程执行)
这里写图片描述

2.mCallback.handleMessage(msg):mCallback(Handler的接口),走接口回调里面的方法

这里写图片描述

handleMessage(msg):send…走这个分支

这里写图片描述

这样,我们对于Handler发送消息,处理消息的流程就很清楚了,以后面试的时候就这个知识点给面试官讲半吧个小时时没有问题了!

关于Handler的几个问题

1.Handler可以new 多个吗?

Handler可以有多个

2.Looper可以有多个吗?

Looper可以有多个,但是一个线程只有一个Looper

3.MessageQueue可以有多个吗?

一个线程只能有一个

Handler通信

1.子线程与主线程通信

1.在子线程中调用send..,post… 
2.在主线程中创建Looper(Looper.prepare),MessageQueue(Application给我们准备好了,不需手动创建) 
3.Handler,Looper,MessageQueue必须在一个线程 
4.主线程收到调用结果

2.主线程与子线程通信

1.在主线程中调用send..,post… 
2.在子线程中手动创建Looper(Looper.prepare),MessageQueue 
3.Handler,Looper,MessageQueue必须在一个线程 
4.子线程收到调用结果

3.子线程A与子线B程通信

A与B通信,A控制B

原创粉丝点击