Android消息传递机制Handler完全解析值面试问答

Android消息传递机制Handler完全解析值面试问答

本文对Handler面试的一些知识题进行总结归档,主要是以文字描述,不熟悉的可以基于某个点再进行深入研究。

面试问题:

分析思路和解答示例

1、说一下你对Handler的理解

提示:这个问题是一个比较笼统的问题,一般要答出Handler的作用,主要的类和类的关系,最好是能说一些细节,比如关于子线程创建Handler,当时不要将太深入。

答案示例:

Handler是消息通信工具,经常被我们用来在子线程接收数据后发送給主线程更新界面;
Handler有三种发送消息方法,立即发送,延时发送和在某个时间发送。
Handler的相关类有Handler、Looper、MessageQueue、Message;
Handler是发消息和接收消息的载体,
Message是消息对象,
MessageQueue是消息管理队列,负责管理消息对象,主要是对消息进行排序,
Looper是循环者,负责把消息从消息队列中获取消息,并发送个Handler对象。
这是消息几个类的相关关系。
但是如果创建Handler后在子线程接收Handler消息,需要注意的是子线程不会自己创建Looper对象和MessageQueue对象,需要先调用Looper.prepare()方法创建MessageQueu和Looper.loop()方法让循环者工作起来,再使用Handler发送和接收消息。

下面提供一篇自己对Handler基础知识的总结:
https://blog.csdn.net/wenzhi20102321/article/details/107888152

2、Handler的实现过程你了解吗

提示:Handler相关的类无非就是Handler、Looper、MessageQueue、Message,主要是把Looper和Message怎么工作的要说清楚,并且说一下Handle发送后是怎么接收到的,这个完整的流程。
想要对这个过程有一定的了解是要分析过源码才能比较清晰的说出;
如果不是很了解,最好不要乱说,就说了解不是很深入,然后说一下上面的handle的理解就行了。

答案示例:

之前看过Handler的源码,对里面的实现有一定的了解;
Handler的整个过程就是Handler对象发送消息,MessageQueue接收消息并以绝对时间值来存储消息对象,Looper从MessageQueue中获取最前面一个即将被处理的消息,并且发送个Handler,之后Handler的回调中就能收到Message消息。

主要的实现过程都在Looper类和MessageQueue里面,
首先是Looper的初始化,会调用Looper.prepare()方法,这个方法主要是创建了MessaageQueu,并且做一些初始化,比如创建工作线程;
Looper初始化后,就调用Looper.loop()方法,让Looper一直工作,让Looper进入while(true)循环不断判断MessageQueue是否有即将处理的消息。
MessageQueue会一直处于接收消息状态,并且对接收的消息进行排序存储;
MessageQueue.next(),这个方法是Looper从MessageQueue取消息的方法,
这个next方法会取出最前面并且即将别处理的消息,即将被处理的意思是这个消息的时间戳的值比当前的时间戳的值大。
但是如果下一个数据是一个延时消息,那么会在这个next()方法进行休眠,这里的休眠不是阻塞sleep,这个休眠是一个native方法休眠线程,会让出cpu給其他进程使用,只要有消息接收或者有消息即将被处理,这个next()方法就会返回Message数据給Looper,Loooper再把数据传給Handler回调。

上面的讲得有点啰嗦,可以适当裁剪一些文字。
下面这篇文章是对Handler源码的详细解析过程,有兴趣可以认真看看:
https://blog.csdn.net/wenzhi20102321/article/details/108431498

3、Handler的延时消息是怎么实现的,会不会造成消息阻塞?

提示:首先说明,不会造成消息阻塞,比如我们一般发送一个延时消息后,再发一个立即发送消息是可以接收到数据的;至于怎么实现,我没看源码的时候,面试的人问我是不是通过定时器,我说可能是吧,但是答案不是定时器,其实是一个底层的线程休眠(不是sleep方法)线程,并且收到消息后或者消息到处理时间后,这个休眠的线程会被唤醒,并继续工作。

答案示例:

不会造成阻塞的情况,因为多个消息会在MessageQeue进行排序,不会影响相互的关系。
Handler延时消息的实现主要是MessageQueue里面的next方法里面,
这个next方法在获取队列最前面一个消息时,如果这个消息还没到处理时间,会调用nativePollOnce方法,这个方法会返线程进入休眠模式,而不是睡眠模式,等到有消息接收或者有最前面一个消息到处理的时间,线程就会停止休眠继续工作,让Looper获取到Message对象,并且回调給Handler。

4、Handler是如何完成子线程和主线程通信的?

提示:主要是说出handler数据是为什么在主线程接收到数据的,从Looper线程和谁发送消息給Handler入手分析即可。

答案示例:

主线程之所以能接收到到数据是因为Looper对象在自己线程的循环方法給Handler发送数据,
而Looper是在主线程创建的,线程是主线程,所有Handler回调的方法是在主线程;
Handler发送数据所在的线程其实无关紧要,主要是看处理Handler的是哪个线程,那么回调数据就是在那个进程。

5、一个线程可以有几个Looper?几个Handler?几个MessageQueue?

提示:一个Looper是绑定一个线程的,并且绑定一个MessageQueue
Handler可以在一个地方创建多个,但是处理Handler消息的线程只能一个,就是跟Looper的线程。

答案示例:

一个looper只能绑定一个线程和一个MessageQueue,一个线程是可以创建多个Handler的。

6、Handler设计用到的什么设计模式

提示:一般的设计模式都不是很记得,何况要把这些知识关联起来
相关是生产者-消费者模式模式和享元模式
生产者-消费者模式不是java标准的23种模式中的一种,而是一种常用场景定义的一种模式,
生产者创建数据,消费者获得数据,中间还有一个缓冲区
生产者是Message对象
缓冲区是Looper和MessageQueue
消费者是Handler对象
还有享元模式指的实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销。
Message创建的时候就用到了享元模式。
在创建Message的时候我们不直接new,而是调用obtain()方法,就是使用到了享元设计模式。

答案示例:

Handler用到了两种java 的设计模式,
一种是生产者-消费者消费者模式,这种模式中间还有个缓冲区,
生产者创建数据后,放到缓冲区,消费者从缓冲区获取到数据,
生产者是Message对象,缓冲区是Looper和MessageQueue,消费者是Handler对象;

另一种是享元模式,享元模式是对象共享的思想,而Message的创建使用的是obtain()方法,可以不用多次创建Message对象,使用的就是享元模式的思想。

上面是Handler常见的面试问题,当然肯定还有其他没有说到的问题,后面慢慢补充;
比如,Handler使用会出现什么问题,这个问题在博客另作补充。

#共勉:在不断反省中前进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值