Handler是用于实现线程间通信和任务调度的一种机(Handler
、 Looper、MessageQueue
、 Message
)。Handler
允许线程间发送Message
或Runnable
对象进行通信。在Android
中UI修改只能通过UI Thread
,子线程不能更新UI
。如果子线程想更新UI
,需要通过 Handler
发送消息给主线程,进而达到更新UI
的目的。
先创建一个与一个线程相关联Handler实例(Handler与创建它的线程相关联,而且也只与创建它的线程相关联),在Handler的构造函数中获取该线程的Looper对象,然后将Handler与Looper绑定。Handler通过post()、sendMessage()等方法将一个Message对象插入到Looper的MessageQueue中,Looper会不断地从MessageQueue中取出Message并将其传递给Handler的dispatchMessage()方法,dispatchMessage()方法负责处理取出的Message,根据Message的类型执行相应的操作,如回调、更新UI等。
一个线程:只有一个Looper,只有一个MessageQueue,可以有多个Handler。
一个 Handler 只能绑定一个线程
子线程默认无 Looper:直接在新线程创建 Handler
会抛出异常,需先调用 Looper.prepare()
和 Looper.loop()
。
1.Message (可携带数据通过what
、arg1
、arg2
、obj
字段)
携带:target=Handler(线程通过target标识发送Message给目标Handler)。
2.Message Queue
存放通过Handler
发送的Message
的消息队列。enqueueMessage(Message msg,long when)
sendMessage发送消息时消息的时间when = SystemClock.uptimeMillis() + delayMillis
SystemClock.uptimeMillis()是手机开机相对时间二者加起来肯定不为0
Message是根据时间有序的插入消息列表的。Message Queue是链表结构(方便增、删操作)
3.Handler
消息处理者,用于发送和接收处理消息。
发送消息 sendMessage()
处理消息 handleMessage()
4.Looper
内部包含一个死循环的MessageQueue
,用于存储handler
发送的Message
,Looper
则是不断的从消息队列中取消,如果有消息就取出发送给Handler
处理,没有则阻塞。
1、面试:Handler A发送的 Message 为啥不会跑到 Handler B的 HandleMessage中被处理?
回答:当handler发送消息时(enqueueMessage)会把自身作为Message的一个属性值(msg.target)封装到Message对象汇总一并发送到消息队列中。 Looper轮循出消息会拿到消息的target属性这样就可以知道每条消息是属于哪个hadler对象的。然后让相应对象的handler进行消息处理。
2、面试:handler.post和handler.sendMessage的区别和联系?
回答:1、handler.sendMessage通过Message
对象(可携带数据通过what
、arg1
、arg2
、obj
字段),传递复杂数据或区分不同消息类型的场景。
2、handler.post不需要Message
对象,直接传递Runnable
。简单任务(如UI更新、延迟操作)
3、底层联系:
handler.post内部会将Runnable
包装成一个Message
(设置callback
字段为该Runnable
),然后调用sendMessageDelayed()
。当Looper
处理该Message
时,会优先执行Runnable.run()
,而非handleMessage()
。
3、Looper死循环为什么不会导致ANR?
回答:应用卡死 ANR压根与Looper没有关系,应用在没有消息需要处理的时候,他是在睡眠,释放线程。卡死是ANR,是如果消息队列里有消息,looper却没有及时处理导致的,和Looper是死循环无关。
4、怎么创建Message?
回答:1、Message message = new message(); 会创建一个全新的Message
对象,增加内存。
2、Message message = Message.obtain(); 从全局的Message
对象池中获取复用实例(避免重复创建)。
3、Message message = handler.obtainMessage();Handler关联的池获取,本质调用Message.obtain()
,但自动绑定当前Handler
。
5、非静态内部类 Handler 发送延迟消息导致Activity内存泄漏的原因?
内存泄漏链路分析:
1、引用链关系:MessageQueue 持有 Message,Message 持有 Handler,非静态内部类 Handler 会隐式持有外部 Activity 的强引用,形成 MessageQueue → Message → Handler → Activity 的引用链。
2、关键节点:
- MessageQueue 持有 Message 的强引用
- Message 持有 Handler 的强引用
- 非静态 Handler 隐式持有 Activity 的强引用
3、生命周期冲突:
Activity 销毁时,若 Message 尚未处理完毕(例如:旋转屏幕后 Activity 无法释放)
整个引用链会阻止 Activity 被 GC 回收
解决方案:
使用静态内部类 + WeakReference
相关文章:
Handler 使用方法介绍
安卓 Handler面试(1)_android handler机制面试-CSDN博客
【Android面试】Android线程间通信Handler消息机制_android handler机制面试-CSDN博客
AskManyAI