Handler的底层原理实现
Posted 永远的红姐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Handler的底层原理实现相关的知识,希望对你有一定的参考价值。
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
以上是关于Handler的底层原理实现的主要内容,如果未能解决你的问题,请参考以下文章