Android面试题:Handler

Android面试题:Handler,第1张

1.一个线程有几个Handler?

答:一个线程可以有多个Handler。

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

答:一个线程只能有1个Looper。Looper对象通过ThreadLocalMap保存,ThreadLocalMap保存键值对,该键值对的键为ThreadLocal对象,一旦ThreadLocalMap中已经存在Looper对象,再次创建Looper对象会抛出异常。

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

答:非静态内部类或者匿名内部类,默认持有外部类的引用。当内部类的生命周期比外部类长时,就会导致内存泄漏。Handler在Activity中作为内部类使用时,handler持有activity的引用。当activity生命周期结束,仍有message没有处理完时,就会导致activity无法被回收,造成内存泄漏。

解决方法:

1. 自定义静态Handler,需要调用activity时,弱引用activity。

2. 在activity的onDestroy()方法中调用handler.removeCallbackAndMessage()方法清空消息队列。

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

答:不能在没有调用Looper.prepare()方法的线程中创建Handler。因为在Handler的构造函数中如果mLooper 对象为空就会抛出异常,只有调用了 Looper.prepare() 方法,才会构造一个 Looper 对象并存储在 ThreadLocal 当中。
主线程中默认已经执行了Looper.prepare()方法,因此可以直接在主线程中new Handler()。在子线程中则需要我们自己先调用Looper.prepare(),然后再去new Handler。

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

答:子线程中Looper.loop()会使Looper一直处于阻塞状态,等待消息的处理。无消息的时候需要调用Looper的quit()方法来结束循环,释放线程。因此在子线程中使用Handler,需要有3个 *** 作:

1. prepare() 创建looper

2. loop() 循环队列

3. quit() 结束循环

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

答:在MessageQueue入队列的方法和取消息的方法中都加了synchronized锁,从而保证了线程安全。

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

答:创建Message对象有三种方法:
1. Message message = new message();
2. Message message = Message.obtain();
3. Message message = handler.obtainMessage();

在实际开发中不建议直接使用new Message。因为在Message内部保存了一个缓存消息池,我们可以用obtain方法从缓存池获取消息,这样能有效避免重复创建Message而造成的内存问题。

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

答:MessageQueue里的消息会以时间顺序(执行的先后顺序)来排序,使用Handler的postDealy后,MessageQueue里的消息会进行重新排序。postDealy发送的消息会根据延迟时间与消息队列里存在的消息的执行时间进行比较,然后寻找插入位置插入消息。

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

答:ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了,Looer.loop()方法可能会引起主线程的阻塞,但只要它的消息循环没有被阻塞,能一直处理事件就不会产生ANR异常。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/740118.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-28
下一篇2022-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存