handler,loop,handlerthread

来源:互联网 发布:常州淘宝培训 编辑:程序博客网 时间:2024/04/30 07:12

 无论是在之前的开发中,还是在最近的面试中,handler跟loop几乎是必接触到的,而最近在面A8音乐时也被问到了handlerthread这个类,现在我就来总结一下三者之间的关系:

  首先来说handlerthread吧,因为他是我最近接触到的,刚在官方文档中看到了它的大概的概述:

  Handy class for starting a new thread thathas a looper. The looper can then be used to create handlerclasses. Note that start() must still becalled.翻译成中文大概是: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. Ifthis thread not been started or for any reason is isAlive() returnsfalse, this method will return null. If this thread has beenstarted, this method will block until the looper has beeninitialized.

 

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 notbeen started or has finished (that is ifgetLooper() 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 thereceiver 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 forthe current thread. If there isn't one, this handler won't be ableto receive messages.

public Handler (Handler.Callbackcallback)

Since: API Level 3

Constructor associates this handler with the queue for thecurrent thread and takes a callback interface in which you canhandle messages.

public Handler (Looperlooper)

Since: API Level 1

Use the provided queue instead of the default one.

public Handler (Looperlooper, Handler.Callback callback)

Since: API Level 3

Use the provided queue instead of the default one and take acallback 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,所以我们说,如果用的不是HandlerThread,而是一个普通的线程,那么如果此时又需要用到looper,那么必须在run方法的第一行写loop.prepare();为什么说looper是用来管理消息队列的,因为通过源码发现:

MessageQueue是在Looper的私有构造函数Looper()中实例化的;

总结一下,HandlerThread是被显式地通过new创建的实例,而与它绑定在一起的Looper是在HandlerThread的执行过程中被实例化的,相应的MessageQueue也是在这个过程中实例化的。

 然后之前我也从不少地方,无论是视频还是论坛里得到的结论是:looper.loop实际上就是一个while(true)的死循环,MessageQueue是Looper保留的一份引用,通过它的next()[序列1]获取MessageQueue中的下一个要处理的消息,这个过程中如果没有相应的消息,执行它的线程会用this.wait()释放它所拥有的MessageQueue的对象锁而等待。

 

0 0
原创粉丝点击