总结一下Handler,Looper,HandlerThread,MessageQueue

转自:http://www.juziku.com/wiki/3880.htm


总结一下Handler,Looper,HandlerThread,MessageQueue

无论是在之前的开发中,还是在最近的面试中,handler跟loop几乎是必接触到的,而最近在面A8音乐时也被问到了handlerthread这个类,现在我就来总结一下三者之间的关系:
   首先来说handlerthread吧,因为他是我最近接触到的,刚在官方文档中看到了它的大概的概述:
  Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.翻译成中文大概是:handlerthread这个类能方便的开启一个包含looper的线程,这个looper也能被用来创建一个handler对象(意思就是把looper以参数形式传递到handler的构造器),并提示我们注意:在用到 handlerthread时,同样必须调用start方法。

Android提供了一个线程类HanderThread类,HanderThread类继承了Thread类,它封装了Looper对象,使我们不用关心Looper的开启和释放的细节问题(因为Looper的构造函数是私有的,对于其实例的获取比较麻烦,而HandlerThread帮我搞定了这些繁琐)。HandlerThread对象中可以通过getLooper方法获取一个Looper对象引用。


其主要的方法有:
 
public Looper getLooper ()
Since: API Level 1
This method returns the Looper associated with this thread. If this thread not been started or for any reason is isAlive() returns false, this method will return null. If this thread has been started, this method will block until the looper has been initialized.

public int getThreadId ()
Since: API Level 1
Returns the identifier of this thread. See Process.myTid().
public boolean quit ()
Since: API Level 5
Ask the currently running looper to quit. If the thread has not been started or has finished (that is if getLooper() returns null), then false is returned. Otherwise the looper is asked to quit and true is returned.
public void run ()
Since: API Level 1
Calls the run() method of the Runnable object the receiver holds. If no Runnable is set, does nothing.

像我之前在项目中使用handler在主线程中对UI进行重绘,其运行机制都是通过发送消息的方式,从子线程中发送消息,然后UI线程中的looper对象接收消息并管理消息队列,默认情况下系统会创建一个无参构造方法的Handler对象,利用这种方法Handler可以自动与当前运行线程(UI线程)的Looper关联,这就是为什么我之前的UI线程中创建Handler时都不需要给其构造器中传递looper对象的原因了。

Public Constructors
public Handler ()
Since: API Level 1
Default constructor associates this handler with the queue for the current thread. If there isn't one, this handler won't be able to receive messages.
public Handler (Handler.Callback callback)
Since: API Level 3
Constructor associates this handler with the queue for the current thread and takes a callback interface in which you can handle messages.
public Handler (Looper looper)
Since: API Level 1
Use the provided queue instead of the default one.
public Handler (Looper looper, Handler.Callback callback)
Since: API Level 3
Use the provided queue instead of the default one and take a callback interface in which to handle messages


通过Handler的这几个构造器就更加知道我之前用法的原因了,完全属于初级阶段,呵呵。
接受消息发送和计划任务的处理是目标线程,它是通过Looper机制维护消息队列,如果应用中有包含更新UI处理,则要把更新UI的处理代码放置在目标线程中,这个时候还要保障更新UI的线程是主线程。

handler发送消息有两种方式,一种是post,另一种是send方式,send方式的话,那么通过handleMessage处理发送过来的消息;Handler对于Message的处理不是并发的。一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的(handleMessage()方法里不应该有耗时操作,可以将耗时操作放在其他线程执行,操作完后发送Message(通过sendMessges方法),然后由handleMessage()更新UI)。

接下来我们再来说说Looper,它是用了收发消息并管理消息队列的,它的构造器是私有的,它的实例化需要通过 loop.prepare()即初始化当前线程为looper,为什么说looper是用来管理消息队列的,因为通过源码发现:
MessageQueue是在Looper的私有构造函数Looper()中实例化的;
总结一下,HandlerThread是被显式地通过new创建的实例,而与它绑定在一起的Looper是在HandlerThread的执行过程中被实例化的,相应的MessageQueue也是在这个过程中实例化的。
  然后之前我也从不少地方,无论是视频还是论坛里得到的结论是:looper.loop实际上就是一个while(true)的死循环,MessageQueue是Looper保留的一份引用,通过它的next()[序列1]获取MessageQueue中的下一个要处理的消息,这个过程中如果没有相应的消息,执行它的线程会用this.wait()释放它所拥有的MessageQueue的对象锁而等待。

猜你喜欢

转载自clevergump.iteye.com/blog/2101886