肥皂起司 2014-08-08
转自:http://www.juziku.com/wiki/3880.htm
总结一下Handler,Looper,HandlerThread,MessageQueue
无论是在之前的开发中,还是在最近的面试中,handler跟loop几乎是必接触到的,而最近在面A8音乐时也被问到了handlerthread这个类,现在我就来总结一下三者之间的关系:
首先来说handlerthread吧,因为他是我最近接触到的,刚在官方文档中看到了它的大概的概述:
Handyclassforstartinganewthreadthathasalooper.Theloopercanthenbeusedtocreatehandlerclasses.Notethatstart()muststillbecalled.翻译成中文大概是:handlerthread这个类能方便的开启一个包含looper的线程,这个looper也能被用来创建一个handler对象(意思就是把looper以参数形式传递到handler的构造器),并提示我们注意:在用到handlerthread时,同样必须调用start方法。
Android提供了一个线程类HanderThread类,HanderThread类继承了Thread类,它封装了Looper对象,使我们不用关心Looper的开启和释放的细节问题(因为Looper的构造函数是私有的,对于其实例的获取比较麻烦,而HandlerThread帮我搞定了这些繁琐)。HandlerThread对象中可以通过getLooper方法获取一个Looper对象引用。
其主要的方法有:
publicLoopergetLooper()
Since:APILevel1
ThismethodreturnstheLooperassociatedwiththisthread.IfthisthreadnotbeenstartedorforanyreasonisisAlive()returnsfalse,thismethodwillreturnnull.Ifthisthreadhasbeenstarted,thismethodwillblockuntilthelooperhasbeeninitialized.
publicintgetThreadId()
Since:APILevel1
Returnstheidentifierofthisthread.SeeProcess.myTid().
publicbooleanquit()
Since:APILevel5
Askthecurrentlyrunningloopertoquit.Ifthethreadhasnotbeenstartedorhasfinished(thatisifgetLooper()returnsnull),thenfalseisreturned.Otherwisethelooperisaskedtoquitandtrueisreturned.
publicvoidrun()
Since:APILevel1
Callstherun()methodoftheRunnableobjectthereceiverholds.IfnoRunnableisset,doesnothing.
像我之前在项目中使用handler在主线程中对UI进行重绘,其运行机制都是通过发送消息的方式,从子线程中发送消息,然后UI线程中的looper对象接收消息并管理消息队列,默认情况下系统会创建一个无参构造方法的Handler对象,利用这种方法Handler可以自动与当前运行线程(UI线程)的Looper关联,这就是为什么我之前的UI线程中创建Handler时都不需要给其构造器中传递looper对象的原因了。
PublicConstructors
publicHandler()
Since:APILevel1
Defaultconstructorassociatesthishandlerwiththequeueforthecurrentthread.Ifthereisn'tone,thishandlerwon'tbeabletoreceivemessages.
publicHandler(Handler.Callbackcallback)
Since:APILevel3
Constructorassociatesthishandlerwiththequeueforthecurrentthreadandtakesacallbackinterfaceinwhichyoucanhandlemessages.
publicHandler(Looperlooper)
Since:APILevel1
Usetheprovidedqueueinsteadofthedefaultone.
publicHandler(Looperlooper,Handler.Callbackcallback)
Since:APILevel3
Usetheprovidedqueueinsteadofthedefaultoneandtakeacallbackinterfaceinwhichtohandlemessages
通过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的对象锁而等待。