1、什么是 Handler?

Handler是异步机制。通过发送和处理Message和Runnable对象来关联相应线程的MessageQueue。

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

2)让自己想要的耗时操作在子线程中完成,让更新UI的操作在主线程中完成,而子线程与主线程之间的通信就是靠Handler来完成。

2、Handler 的使用方法

常用方法有 post()、sendMessage();先看构造器。

Handler(): 默认构造函数将此处理程序与Looper用于当前线程。

Handler(Handler.Callback callback):构造函数将此处理程序与Looper对于当前线程,并接受一个回调接口,您可以在其中处理消息。

Handler(Looper looper):使用所提供的Looper而不是默认的。

Handler(Looper looper, Handler.Callback callback):使用所提供的Looper而不是默认的,而是接受一个回调接口来处理消息。

接下来我们就来看看Handler提供的各种方法吧:

post(Runnable r):导致将Runnable r添加到消息队列中。

postAtTime(Runnable r, long uptimeMillis):使Runnable r添加到消息队列,并在uptimeMillis.

postDelayed(Runnable r, long delayMillis):使Runnable r被添加到消息队列,并在指定的时间流逝后运行。

removeCallbacks(Runnable r):删除消息队列中所有可运行的Runnable消息任务。

removeMessages(int what):删除消息队列中消息对象what字段为"what"的消息任务。

sendEmptyMessage(int what):发送一个空消息对象,并设置这个空消息的what值。

sendEmptyMessageAtTime(int what, long uptimeMillis):发送只包含要在特定时间传递的值的消息。

sendEmptyMessageDelayed(int what, long delayMillis):发送一条消息,该消息只包含要在指定的时间间隔后传递的值。

sendMessage(Message msg):将消息推送到消息队列的末尾,在当前时间之前完成所有挂起的消息。

sendMessageAtTime(Message msg, long uptimeMillis):在所有挂起的消息在绝对时间之前uptimeMillis(以毫秒为单位)之前,将消息放入消息队列中。

sendMessageDelayed(Message msg, long delayMillis):在所有挂起的消息之前(当前时间+delayMillis)之后,将消息放入消息队列中。

3、Handler 内部的实现机制

Handler机制也叫异步消息机制,由4部分组成:Message+Handler+MessageQueue+Looper

1)Message

Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。使用Message的arg1和arg2便可携带int数据,使用obj便可携带Object类型数据。

2)Handler

用于在子线程发送消息对象Message,在UI线程处理消息对象Message,在子线程调用sendMessage方法发送消息对象Message,而发送的消息经过一系列地辗转之后最终会被传递到Handler的handleMessage方法中,最终在handleMessage方法中消息对象Message被处理。

3)MessageQueue

消息队列。用于存放所有通过Handler发送过来的消息。这部分消息会一直存放于消息队列当中,等待被处理。每个线程中只会有一个MessageQueue对象,请牢记这句话。其实从字面上就可以看出,MessageQueue底层数据结构是队列,而且这个队列只存放Message对象。

4)Looper

管理 MessageQueue。调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当MesssageQueue中存在一条消息,Looper就会将这条消息取出,并将它传递到Handler的handleMessage()方法中。每个线程只有一个Looper对象。

小结:

首先 UI线程创建一个 Handler实例对象handlerA,必须重写 handlerMessage(),在此方法中通过参数 msg进行 UI线程的逻辑处理。

然后创建子线程,在需要更新 UI的时候,新建一个 Message对象 msgB,并把要传递的消息放在 Message内部:arg1,arg2,obj等。

最后,通过 handlerA.sendMessage()把 msgB发送出去;之后这个 msgB会被放到 MessageQueue中等待被处理,此时 MessageQueue的管家 Looper正在不停取消息,通过调用 dispatchMessage()将消息传递给 handlerA.handlerMessage()。

4、Handler引起的内存泄露以及解决方法。

原因:非静态内部类持有外部类的匿名引用,

解决方法:handler内部持有外部的弱引用,并把handler改为静态内部类,在activity的onDestory()中调用handler的removeCallback()方法。

5、如何使用 Handler让子线程与子线程之间进行通信?

简单来说,如何让 子线程A与 子线程B进行 Handler通信?

1)首先你得在 ThreadA中准备一个Looper以及 Handler。

2)在 ThreadA中,调用 Looper.prepare(),最后调用 Looper.loop()。源码是有例子。

6.Handler底层原理

以下是 Framework层知识体系。