什么是handler?

异步消息处理机制相关面试问题-handler面试问题详解_构造函数

 这个异常应该也就是引出handler的原因,也就是默认在非UI线程中是无法去更新UI的东东滴,那到底什么上handler呢?

handler通过发送和处理Message和Runnable对象来关联相对应线程的MessageQueue。

1、可以让对应的Message和Runnable在未来的某个时间点进行相应处理。

2、让自己想要处理的耗时操作放在子线程,让更新UI的操作放在主线程。

handler的使用方法:


  • post(runnable)
    查看一下代码其实它也是调了用sendMessage(),如下:
    异步消息处理机制相关面试问题-handler面试问题详解_内存泄漏_02
  • sendMessage(message)

handler机制的原理:

先来看一下图:

异步消息处理机制相关面试问题-handler面试问题详解_内存泄漏_03

从源码角度来分析,先来看一下handler()的构造函数会来创建一个looper:

异步消息处理机制相关面试问题-handler面试问题详解_子线程_04

然后还创建了MessageQueue:

异步消息处理机制相关面试问题-handler面试问题详解_子线程_05

可以发现MessageQueue是在Looper里面创建的,那Looper是如何创建的呢?

异步消息处理机制相关面试问题-handler面试问题详解_子线程_06

是通过ThreadLocal来获取的,也就是不同的线程获取各自的Looper,那何时将Looper对象放到ThreadLocal当中的呢?

异步消息处理机制相关面试问题-handler面试问题详解_子线程_07

异步消息处理机制相关面试问题-handler面试问题详解_子线程_08

此时Handler就持有的MessageQueue,而MessageQueue又是在Looper当中创建的,这样这三者就有机的关连起来了。

接着Looper需要调用loop()方法从MessageQueue去获取消息并处理,具体看下源码:

异步消息处理机制相关面试问题-handler面试问题详解_构造函数_09

而msg.target中的tartget又是个什么东东呢?

异步消息处理机制相关面试问题-handler面试问题详解_子线程_10

哦~~原来就是Handler,接着再来看一下它的dispatchMessage()方法:

异步消息处理机制相关面试问题-handler面试问题详解_内存泄漏_11

而像Msg.obtain()方法就是用callback的形式,至此整个handler消息处理过程就已经完整分析了,下面再来用图回顾一下:

异步消息处理机制相关面试问题-handler面试问题详解_构造函数_12

handler引起的内存泄漏以及解决办法:

 异步消息处理机制相关面试问题-handler面试问题详解_内存泄漏_13

解决方法:

①、可以将handler声明为静态内部类,如下:

异步消息处理机制相关面试问题-handler面试问题详解_构造函数_14

②、也可以在Activity中的onDestroy()中调用如下方法:

异步消息处理机制相关面试问题-handler面试问题详解_内存泄漏_15

③、让handler内部持有外部Activity的弱引用。