Thread\Handler\Looper\MessageQueue之间的关系

【欢迎转载,但请注明出处】博客园:http://www.cnblogs.com/byirain/archive/2013/04/21/3031001.html

你需要

前面对Handler,Looper作了一些总结,阅读此篇前建议大家先看一下:

1.android多线程与UI操作

2.android之handler总结

3.android之Looper

什么关系

那么Thread、Handler、Looper、MessageQueue、Message之间到底是个什么关系呢?

请看下图:

 所属关系图

1.通过翻看源码可以看到在Looper中有一个ThreadLocal<Looper> sThreadLocal,其中存放的就是与当前Thread对应的Looper

2.Looper中维护的有一个消息队列

3.一个消息队列中可以有若干个消息

4.一个Thread中可以创建多个Handler对象,它们各自发送的消息最终有各自处理不会混淆,因为Message对象维护的有一个Handler对象target

再来看一下它们对应关系图

主线程:默认有一个Looper。所以可以直接在主线程中实例化Handler

子线程:默认无Looper。若想在子线程中创建Handler对象,则必须先在其中创建Looper

Looper:操作MessageQueue

Handler:投递Message。并最终在DisptchMessage中处理消息

MessageQueue:消息队列

Message:消息实体。主要参数:arg1,arg2,obj,handler,runnable

 

模拟一个过程

  试着模拟一个过程就用android多线程与UI操作中的例子。

针对方案1的模拟过程:

  首先我们在主线程中new一个全局Handler对象myHandler,然后再新开一个子线程用来完成从网络上下载bitmap的操作,然后再在此子线程中调用myHandler的post方法将更新UI的操作放到UI线程中执行。完成。

  在这个过程中,有两个Thread一个主线程,一个子线程。我们用主线程中的myHandler将要执行的更新操作的Runnable对象post到主线程中执行。从Handler源码中我们可以看到,实际上是这样做的:首先myHandler将此Runnable对象封装成一个Message对象msg然后再调用handler的sendXXX方法将此message对象发送到myHandler所在线程即主线程中的消息队列中,那么sendXXX()方法是如果将此msg发送到主线程中的消息队列中去的呢?  通过翻看sendXXX()的源码我们可以看到,它最终是通过调用MessageQueue的enqueueMessage(Message msg, long when)方法完成新消息的入队操作的。

  先总结一下:到目前为之我们还没有发现有用到Looper。我们已经完成了消息的发送及入队过程,在这个过程中我们只用到了myHanler,及MessageQueue。(但其实Looper在Handler被创建之前就存在了)

 

  接着往下走,下面就是消息的处理过程了。现在我们知道,在UI主线程有一个消息对列messageQueue,其中就有我们刚发送的那个msg。但是,消息队列中那么多消息主线程是如何处理的呢。这个时候looper起到了关键作用。我们知道我们要想new Handler,必须首先在此Handler所在线程中new 一个Looper对象,从Handler的那么多构造方法中我们也可以感受到这一点,但我们的Handler是在主线中的所以我们不必自己去new,主线程默认就有一个,所以在我们new Handler的那一刻起我们不仅有了一个handler还有了一个与此handler对应的looper对象,并且上面我们也说过了消息对列messageQueue是依附于looper的,所以到现在我们有了handler及与之对应的looper及与之对应的messageQueue对象 。

  下面我们看一下looper源码,可以看到其中有一个loop方法,其实这个方法中就是一个死循环,不断的从消息队列中取出消息然后再交给Handler的 dispatchMessage(msg)处理。至于dispatchMessage方法是如何处理的可以看一下本文前面给的那几个链接的文章。其中有详细分析。

  至此,整个消息的发送及处理过程就完成了。

 

总结:

  a.Thread中默认无looper,但主线程中默认系统已经创建好了一个Looper对象。android中有一个HandlerThread

类,它提供了一个Thread及与之对应的Looper。

  b.Looper对象,它其中有一个loop方法在不断的循环,从MessageQueue队列中取出队首的Message交给与之关联的Handler对象处理

  c.一个线程中只能有一个looper对象,只能有一个MessageQueue,此looper与MessageQueue是一一对应的关系。

  d.Thread中默认无Handler,若需要创建Handler要先在此Thread中创建一个looper

  e.不一定只能在主线程中进行消息的处理。我们也可以在子线程中处理,当然只能处理非UI相关的。

      假设,我们需要在一个子线程中处理消息,那么首先我们要在此线程中创建一个looper对象,然后再创建一个handler对象并重写handlerMessage方法(不一定非要这样,还可以实现Callback接口,具体请看前文链接中的文章),然后再在需要发送消息的线程(比如主线程及别的子线程)中调用此handler对象即可。

附上一张在网上找的图:

上面都是自己读源码及网友的博客根据自己的理解总结的,不妥之处欢迎批评指正。

PS:发现写好一篇博文真不容易.

参考:http://www.aviyehuda.com/2010/12/android-multithreading-in-a-ui-environment/

原文地址:https://www.cnblogs.com/byghui/p/3031001.html