Handler Looper MessageQueue源码解析

Handler依赖于Looper,它的创建需要该线程下的Looper已经存在,而该 Looper又会有与当前的线程进行绑定,所以该Handler所处线程就是Looper创建时所在的线程。

Handler的dispatchMessage方法是在创建Handler时所用的Looper中执行的,这样就成功的将代码逻辑切换到指定的线程中去执行了。

所以,handler发送消息(send)可以在任意的线程中,但是接收消息一定是在创建Handler时所用的Looper中的线程里。

Looper

先解释一下ThreadLocal类

/**

 * Implements a thread-local storage, that is, a variable for which each thread

 * has its own value. All threads share the same {@code ThreadLocal} object,

 * but each sees a different value when accessing it, and changes made by one

 * thread do not affect the other threads. The implementation supports

 * {@code null} values.

 *

 * @see java.lang.Thread

 * @author Bob Lee

 */

public class ThreadLocal<T> {

set()和get()方法必须要在同一个线程中进行,否则get()中取不到值(所以ThreadLocal.get()获得得就是当前线程对应的Looper对象)

ThreadLocal 不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制

ThreadLocal是一个用来存储当前线程状态的一个成员变量,存储范围为线程内部

ThreadLocal是一个线程内部类的数据存储类,通过它可以在指定的线程中去存储数据,数据存储之后,只有在指定的线程中可以获得存储的数据,对于其他线程来说无法获取到数据

应用程序使用Lopper分为两种情况

一.主线程中使用Lopper

通过myLooper()方法可以得到当前线程的Looper对象

二.非主线程中使用Looper

Lopper对象的创建

无论是创建与主线程关联的Looper对象还是创建与子线程关联的Looper对象,都会调用

private Looper(boolean quitAllowed) {

mQueue = new MessageQueue(quitAllowed);

mThread = Thread.currentThread();

}

在创建Looper的同时,创建一个与之对应的MessageQueue

那么MessageQueue中的bool类型的参数quitAllowed又是干什么的呢?

我们跟进去看到最终这个参数会在MessageQueue的quit中用到

这样我们就明白了,与主线程,子线程关联的Looper对象创建过程都一样,只不过一个传入true,一个传入false

目的在主线程中创建的Looper是必须一直存在的,该Looper所对应的MessageQueue也是不可退出的。

为什么我会说主线程中创建的Looper是不允许退出的呢?可以看看Looper的quit()方法

这里直接调用了与之关联的MessageQueue中的quit方法,这样我们就明白了。

让Lopper工作起来

/**

 * Run the message queue in this thread. Be sure to call

 * {@link #quit()} to end the loop.

 */

public static void loop() {

final Looper me = myLooper();

if (me == null) {

throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread.");

}

final MessageQueue queue = me.mQueue;

// Make sure the identity of this thread is that of the local process,

// and keep track of what that identity token actually is.

Binder.clearCallingIdentity();

final long ident = Binder.clearCallingIdentity();

for (;;) {

Message msg = queue.next(); // might block

if (msg == null) {

// No message indicates that the message queue is quitting.

return;

}

// This must be in a local variable, in case a UI event sets the logger

Printer logging = me.mLogging;

if (logging != null) {

logging.println(">>>>> Dispatching to " + msg.target + " " +

msg.callback + ": " + msg.what);

}

msg.target.dispatchMessage(msg);

if (logging != null) {

logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);

}

// Make sure that during the course of dispatching the

// identity of the thread wasn‘t corrupted.

final long newIdent = Binder.clearCallingIdentity();

if (ident != newIdent) {

Log.wtf(TAG, "Thread identity changed from 0x"

+ Long.toHexString(ident) + " to 0x"

+ Long.toHexString(newIdent) + " while dispatching to "

+ msg.target.getClass().getName() + " "

+ msg.callback + " what=" + msg.what);

}

msg.recycleUnchecked();

}

}

loop()方法的只要作用就是开启一个for循环,不停的去询问MessageQueue中是否有Message

我们重点看一下msg.tar.dispatchMessage(msg)这个方法

msg.tar获得的是与这个Message相对应的Handler对象,我们去看看Handler中的dispatchMessage(Message msg)方法

具体分析这个方法在Handler章节,这里只需要知道,loop中会从MessageQueue中取出Message,并交给该Message对应的Handler进行处理

总结

通过分析Looper对象的创建过程,可以得到以下结论

1.Looper可以与主线程/子线程一对一进行关联

2.Looper与MessageQueue也是一对一的关联

3.

这就解释了,为什么在子线程中,想要创建Looper对象,必须先调用Looper.prepare()方法,而与主线程对应的Looper在进程启动时就已经创建了(后面会涉及到),所以主线程中不需要显示的创建Looper对象

也解释了为什么子线程中想要让Looper运行起来,为什么要调用Loop.loop()方法

Handler

先从创建Handler对象说起

Handler有如下7个构造函数

Handler(),Handler(Callback),Handler(boolean)---->都会调用Handler(Callback,boolean)

Handler(Looper),Handler(Looper,Callback)----->都会调用Handler(Looper,Callback,boolean)

我们来具体分析一下这两个方法

Handler(Callback,boolean)

/**

 * Use the {@link Looper} for the current thread with the specified callback interface

 * and set whether the handler should be asynchronous.

 *

 * Handlers are synchronous by default unless this constructor is used to make

 * one that is strictly asynchronous.

 *

 * Asynchronous messages represent interrupts or events that do not require global ordering

 * with respect to synchronous messages.  Asynchronous messages are not subject to

 * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.

 *

 * @param callback The callback interface in which to handle messages, or null.

 * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for

 * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.

 *

 * @hide

 */

public Handler(Callback callback, boolean async) {

if (FIND_POTENTIAL_LEAKS) {

final Class<? extends Handler> klass = getClass();

if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&

(klass.getModifiers() & Modifier.STATIC) == 0) {

Log.w(TAG, "The following Handler class should be static or leaks might occur: " +

klass.getCanonicalName());

}

}

mLooper = Looper.myLooper();

if (mLooper == null) {

throw new RuntimeException(

"Can‘t create handler inside thread that has not called Looper.prepare()");

}

mQueue = mLooper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

可以看到,用这种方式创建Handler默认是该Handler所处的线程中已经创建好了Looper实例。

如上节Looper中讨论的,MainThread中的Looper在程序启动时就已经创建完毕,所以主线程中可以用这种方式直接创建

而子线程中,必须现在该线程中调用Looper.prepare()方法,然后再创建Handler,接着再调用Looper.loop()方法进行循环取消息

Handler(Looper,Callback,boolean)

/**

 * Use the provided {@link Looper} instead of the default one and take a callback

 * interface in which to handle messages.  Also set whether the handler

 * should be asynchronous.

 *

 * Handlers are synchronous by default unless this constructor is used to make

 * one that is strictly asynchronous.

 *

 * Asynchronous messages represent interrupts or events that do not require global ordering

 * with respect to synchronous messages.  Asynchronous messages are not subject to

 * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.

 *

 * @param looper The looper, must not be null.

 * @param callback The callback interface in which to handle messages, or null.

 * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for

 * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.

 *

 * @hide

 */

public Handler(Looper looper, Callback callback, boolean async) {

mLooper = looper;

mQueue = looper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

再看一下Looper中遗留的dispatchMessage(Message msg)方法

做的事情就是将Handler发送的Message传递给该Handler来进行处理

之前分析到,dispatchMessage(Message msg)方法是在Looper.loop方法中被调用的

发送消息(本质就是将Message压入MessageQueue)

handler.post(Runnable)

handler.sendMessage(Message)

post是将一个Runnable投递到Handler内部的Looper中去处理

sendMessage是将一个消息投递到Handler内部的Looper中去处理

post最终也会调用sendMessage方法来完成

handler.post(new Runnable() {

@Override

public void run() {

textView.setText("456");

}

});

通过handler.post可以直接更改UI,这里的Message就是456

MessageQueue

消息队列是由nativie的代码(JNI)创建的

Message

/**

 * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.

 * @param 
Handler to assign to the returned Message object‘s <em>target</em> member.

 * @return A Message object from the global pool.

 */

public static Message obtain(Handler h) {

Message m = obtain();

m.target = h;

return m;

}

这里可以看出,每个Message只能制定一个Handler进行处理

总结

一个Thread对应一个Looper

一个Looper对应一个MessageQueue(只循环从这个MessageQueue中获得消息并调用该Message对应Handler的dispatchMessage方法)

一个MessageQueue对应多个Message

一个Message又只能指定一个Handler进行处理

所以

一个Thread可以对应多个Handler,是一对多的关系

ActivityThread

整个应用程序就是从ActivityThread的main()函数开始的

与主线程相对应的Looper对象就是在main方法中通过

Looper.prepareMainLooper()创建的

重点如下:

1.创建处理消息的环境

2.循环处理消息

也就是说,消息是推动这个系统动起来的基础,即便操作系统也是如此。

Thread

时间: 2024-11-08 06:32:55

Handler Looper MessageQueue源码解析的相关文章

Android Handler消息机制源码解析

好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个类合作完成,分别是Handler,MessageQueue,Looper,Message Handler : 获取消息,发送消息,以及处理消息的类 MessageQueue:消息队列,先进先出 Looper : 消息的循环和分发 Message : 消息实体类,分发消息和处理消息的就是这个类 主要工

Handler机制(三)----Looper源码解析

一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and

Handler机制(四)---Handler源码解析

Handler的主要用途有两个:(1).在将来的某个时刻执行消息或一个runnable,(2)把消息发送到消息队列. 主要依靠post(Runnable).postAtTime(Runnable, long).postDelayed(Runnable, long).sendEmptyMessage(int).sendMessage(Message).sendMessageAtTime(Message).sendMessageDelayed(Message, long)这些方法来来完成消息调度.p

深入源码解析Android中的Handler,Message,MessageQueue,Looper

本文主要是对Handler和消息循环的实现原理进行源码分析,如果不熟悉Handler可以参见博文< Android中Handler的使用>,里面对Android为何以引入Handler机制以及如何使用Handler做了讲解. 概括来说,Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制.我们在使用Handler的时候与Message打交道最多,Message是Hanlder机制向开发人员暴露出来的相关类,可以通过Message类完成大部分操作Handler的功能.但

Android消息机制Handler、Looper、MessageQueue源码分析

1. Handler Looper MessageQueue的关系 2.源码分析 下图表示了Handler.Looper.MessageQueue.Message这四个类之间的关系. Handler必须与一个Looper关联,相关Looper决定了该Handler会向哪个MessageQueue发送Message 每一个Looper中都包含一个MessageQueue Handler中的mQueue引用的就是与之关联的Looper的MessageQueue 不管Handler在哪个线程发送Mes

android源码解析--Handler

转载自:http://blog.csdn.net/lilu_leo/article/details/8143205 开始,先看下android官方对于Handler的解释: [java] view plaincopy /** * A Handler allows you to send and process {@link Message} and Runnable * objects associated with a thread's {@link MessageQueue}.  Each 

Android培训HandlerThread的使用及源码解析

Android培训HandlerThread的使用及源码解析-北京尚学堂 关于Hanlder的基本使用可以参见博文<Android中Handler的使用>,如果想了解Handler.Looper.Thread等的相互关系以及内部实现原理可以参见博文<深入源码解析Android中的Handler,Message,MessageQueue,Looper>. Android中的API中对HandlerThread的描述是: Handy class for starting a new t

Android异步消息处理机制(2)源码解析

上一章讲解了Android异步消息处理机制的基本使用,下面将简单地探寻一下异步机制背后的奥妙,源码版本为:API22. 首先,声明一下本文是在我参考了一下各位大神的文章之后才慢慢熟悉的, 若有不足之处,还望各位批评指正!.菜鸟上路,,,, 郭霖博客 鸿洋博客 刘超 深入解析android5.0系统 任玉刚博客 先后顺序按照拼音排序,无关技术本身. 先简单地总结一下Looper,MessageQueue,Message和Handler四者之间的关系: Looper和MessageQueue Loo

Android -- AsyncTask源码解析

1,前段时间换工作的时候,关于AsyncTask源码这个点基本上大一点的公司都会问,所以今天就和大家一起来总结总结.本来早就想写这篇文章的,当时写<Android -- 从源码解析Handle+Looper+MessageQueue机制>的时候就是想为这篇文章做铺垫的,因为AsyncTask说里面还是使用的handle,所以先就写了handle这一篇.记得15年底去美团面试的时候,面试官就问我既然存在handle为什么google还要出AsyncTask(毕竟底层还是用的handle+Exec