这个是我最常用的android端面试题。首要它是整个android体系运作的根底,其次是大多数app开发都会使用到/接触过,最终该问题扩展性十分强,小到简略使用,framework技巧,大到黑科技,无声明activity发动都用涉及到。一般情况下面试是这个样子
0、能请你聊一下android的handler机制吗?
大部分答复会是这么个样子:handler机制涉及handler,messagequeue、message、looper四个部分,handler负责将音讯message投递到messagequeue里边,looper是一个死循环,从messagequeue里边取出音讯进行处理。略微细节一点点的同学会加上looper会将获取到的音讯dispatch给对应的handler进行处理。看过源码的同学会装一下,和面试官掰扯一下源代码,函数调用过程,looper.prepare,messagequeue.next,nativepollonce,大概如此
上面的答复是散乱的,比较小白的,基本上判别为面经八股文,死记硬背。
- 需求体现你的考虑过程,你要为这个工作定基调。譬如:
handler机制是android体系运转的根底,它选用出产者,消费者形式进行规划。其间出产者是handler,多个handler会出产音讯message投递到线程同享的messagequeue有序单链表里边,再由线程同享looper进行消费,将message音讯dispatch到其指定的handler进行处理。
- 需求体现你的面广,你需求说明android体系都怎样根据handler机制运作。
无论是activity/service/fragment的生命周期都根据handler机制运作,ui视图改写/动画体系播映也是经过handler进行同步改写,手机屏幕的接触事件也是根据handler机制进行呼应分发。
第一阶段已经将handler机制表述得十分清楚。
这里有几个细节要注意一下:
- handler的规划形式是出产者消费者(能够进一步问message是什么规划形式)
- messagequeue/looper是线程唯一同享的(能够进一步问ThreadLocal的原理)
- messagequeue是一个有序的单链表结构(能够进一步问怎样完成高效查询)
1、looper.loop是个死循环,messagequeue.next也是个死循环,假如messagequeue取不到音讯的时分,会产生什么情况,cpu会不会跑满100%?
绝大多数同学对这段代码没有细抠,而是简略回复由于nativepollonce选用了了epoll机制,当没有取到音讯的时分会挂起线程让渡cpu,等下一次音讯抵达的时分重新唤醒线程持续履行,所以cpu不会跑满100%。我们来整理一下,从messagequeue中取不到音讯不代表里边没有音讯,假如当前主线程这时分挂起并让渡cpu,鄙人次音讯抵达唤醒线程,怎样保证线程能竞争到cpu资源? 有同学回复是由于前台线程优先级高。首要app还真不必定处于前台,其次前台线程也不仅仅是一个,android是多任务调度的体系,会有多个前台进程,这是第一个坑点。第二个坑点便是,messagequeue里边有一个闲时处理器,idlehandler的机制,当从messagequeue取不到音讯的时分会履行idlerhandler(如有),一个线程不可能又是挂起,又是履行的,上面的答复能够更谨慎一点。
真实的情况是怎样的呢?
- 首要不会马上让渡cpu,这样才有往下履行idlehandler的根底。假如从messagequeue中取不到音讯,会持续往下履行判别是否有idlehandler,假如有就从里边获取最多5个idlehandle并履行,设置循环等候标识0,持续测验获取音讯;假如没有任何idlehandle就设置循环等候标识-1,自循环等候音讯。
- 其次nativepollonce会阻塞是真的,不过有超时条件,也便是上面提到的循环等候标识设置,0标识查询没有可用(ready)的message就立即返回,-1表明等候直到有可用音讯才返回,其他表明超时等候时刻,一般是下一个音讯when减去当前now时刻,超时即返回。
- 最终epoll是根据linux内核工作,多路复用体现在1个内核线程监控多个fd状况,epoll比较高效是由于被监控fd状况ready了才会被查询到,从而得到处理。epoll等候会设置当前线程interrupt状况等候唤醒。
2、有没有使用过handler?处理什么问题?你在哪些源码结构上看待handler的使用?
中规中矩的答复便是经过handler处理子线程与主线程切换。实际上这里边考察的面十分广,考察基本功也是深的。
- 从规划形式视点看这个问题,完完全全便是多出产者单消费者形式;这个形式典型使用在哪些场景?android里边的toast的完成就很经典了。
- 假如这个handler再搭配上子线程,我们会发现internservice便是一个典型的使用场景,先处理完一个intern,然后再处理下一个,单线程,有序地进行。
- idlehandler也有用于发动加速的,不过体系里边更典型的使用是activity的destroy生命周期调度,鄙人一个activity发动之后再经过idlehandler进行上一个destroy的调度,搭配上10s钟超时强制履行destroy,这也是为什么activity回收必然是10s内的原因。
- binder通信里边也不缺少handler的使用。
- 还有更多,大家自行发现。
3、其他的一些细节&具体使用场景问题
- 同步音讯/异步音讯是怎样回事?音讯栅栏是一个什么情况?
- messagequeue怎样排序的?handler怎样高效完成优先处理异步音讯?
- 怎样完成在manifest文件无声明activity发动?占坑方式的插件化怎样完成?
- 怎样处理view的bad token崩溃?
- 怎样计算主线程调用耗时?
- 怎样监控binder进程调用耗时?
- epoll为什么选用红黑树结构?
- ……
定论
我个人觉得并不是必定要通读源码才是完美无缺的,而是理解其原理,知晓其奥妙,把握使用场景,知行合一,从更多视点去了解其是怎样使用的,然后自己再有足够的技术判别力来觉得其是否合适,那么这个知识便是归于你的。
- 0、Handler机制面试中的坑
- 1、android面试View的问答技巧
- 2、android面试线程&多线程
- 3、android面试结构&选型
- 4、android面试性能问题&优化&实践
- 5、android面试dalvik&asm&hook
- 6、android面试aapt&d8&r8&dex