Android自己的面试准备 (Handler篇)持续更新中……

    自己终于是下定决心裸辞了。下面记录自己从各个地方搜索出的面试题以及答案。仅作自己记录,记忆使用。

一、关于必问的Handler知识

    1.一个线程有几个Handler?

    答:一个线程可以有多个Handler,比如主线程使用Handler时,可以new多个使用。

    2.一个线程有几个Looper?如何保证?

    答:一个线程只有一个Looper,因为ThreadLocal代码中有获取Looper的方法,就是获取当前的线程id,作为key,来从map中取出Looper对象的。有需要验证的可以自行去翻Handler源码

    3.Handler内存泄漏原因?为什么其他的内部类没有说过有这个问题?

    答:因为Looper对象会有耗时的操作(一直在轮询是否有消息的时间应该被执行了),Looper持有了Handler对象,Handler对象持有了Activity对象。故而可能导致内存泄露。

    专业一点的说就是:内部类持有了外部类的对象。为什么其他内部类没有,上面说了。是因为内部类有耗时操作,当内部类没有耗时操作时,当然就不会一直持有外部的对象了。故而其他的内部类没有这个问题。

    4.为何主线程可以new Handler?如果想要在子线程中new Handler 要做些什么准备?

    答:在主线程可以new Handler 是因为在app启动时会先走ActivityThread的main方法,这里Looper先后执行了,prepare和loop方法。这里是初始化主线程Looper的地方,这两个方法不走,Looper是不会被执行的,

    当然Looper不会被执行,你sendMessage也就不会执行了。故而我们可以直接在Activity中可以直接new Handler,就是因为系统已经帮我们初始化并且启动了Looper了。

    回答完上述这个问题后,再回答第二个问题就简单了。可以在子线程中new Handler,但是这个时候我们就必须自己初始化并且启动当前线程的Looper了。故而需要执行Looper的prepare和loop方法。就可以顺利的在

    子线程中使用Handler了。

    5.子线程中维护的Looper,消息队列无消息的时候的处理方案是什么?有什么用?

    答:想要回答这个问题,就必须要明白一件事情,这个问题为什么会被问出来。因为Looper的机制,Looper当开始后,会一直轮询MessageQueue有没有Message需要发送出去。在子线程中如果我们发送完了一个消息,

    并且也执行完毕了。这个时候就要考虑关闭Looper的循环了。如果不关闭,那么子线程loop后的代码就不会执行了,因为一直在Looper中循环,不会被跳出去。所以需要调用Looper的quit方法,这个时候Looper.loop

    后面的代码就会被执行了。

    6.既然可以存在多个Handler 往 MessageQueue 中添加数据(发消息时各个Handler可能处于不同线程),那它内部是如何确保线程安全的?

    答:我们还是查看源代码得知,MessageQueue的enqueueMessage方法中加锁了,正式这个原因,才保证的内部线程安全。

    7.我们使用Message 时应该如何创建?

    答:要用Message.obtain 而不是直接new,因为从源码Message的obtain方法中可以看到维护message的是一个单链表。这里的代码证明如果有空闲的message那么将会进行复用,而不是重新创建一个message。

    为什么会有空闲的Message的,这里要看Message中的recycleUnchecked,这个方法是message被执行完成的时候调用的。这里看到并不是把Message值为null,而是把其中的参数置为空了。所以Message还会在单链表中,

    因此我们使用Message创建时,应该使用obtain方法

    8.使用Handler的postDelay后消息队列会用什么变化?

    答:消息不会被立即执行,它会计算等待的时间,然后再睡眠,等待时间到时再执行发送message

    9.Looper死循环为什么不会导致应用卡死?

    答:因为app的主线程所有的操作都会跑在Looper执行的,这里Looper死循环,只是睡眠而已,等用户有新的操作时,即可以唤醒Looper,继续执行。这里是睡眠和唤醒的过程,和anr没有关系

   10.简述一下Handler的执行流程

    答:Handler.sendMessage方法会加入一个消息到MessageQueue队列中,加入的方式是根据时间插入的,然后Looper一直会循环MessageQueue队列,看当前的时间是否到了可以从MessageQueue队列中取出数据的时间,

    若发现时间到了,那么就会调用handler的 handlerMessage方法,从而我们就收到消息了

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值