【欢迎转载,但请注明出处】博客园:http://www.cnblogs.com/byirain/archive/2013/04/21/3031001.html
你需要
前面对Handler,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/