一、Thread的源码分析:
路径:sdk\sources\android-16\java\lang\Thread.java
重要函数分析:
start方法是启动线程的重要方法。源码分析如下:
public synchronized void start() { //判断是否重复启动,是就抛出异常。说明任何线程只能start一次。 if (hasBeenStarted) { throw new IllegalThreadStateException("Thread already started."); // TODO Externalize? } hasBeenStarted = true; //调用虚拟机中的创建线程功能。会在创建线程后,调用run方法。 VMThread.create(this, stackSize); }
大部分线程构造函数都调用create方法。源码分析如下:
private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { Thread currentThread = Thread.currentThread();//取得主线程对象 if (group == null) { group = currentThread.getThreadGroup(); } if (group.isDestroyed()) { throw new IllegalThreadStateException("Group already destroyed"); } this.group = group;//赋予主线程的gid synchronized (Thread.class) { id = ++Thread.count; } if (threadName == null) {//当没有给线程名的时候,自动产生与id有关线程名 this.name = "Thread-" + id; } else { this.name = threadName; } this.target = runnable; this.stackSize = stackSize; this.priority = currentThread.getPriority(); this.contextClassLoader = currentThread.contextClassLoader; // Transfer over InheritableThreadLocals. if (currentThread.inheritableValues != null) { inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues); } // add ourselves to our ThreadGroup of choice this.group.addThread(this);//一般加入主线程所在组,指定组的构造函数不调用create。 }
二、Handler源码分析:
路径:sdk\sources\android-16\android\os\Handler.java
重要函数分析:
Callback接口
/** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. */ public interface Callback {//定义了内部接口Callback public boolean handleMessage(Message msg); } /** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) {//定义了Handler自己的消息处理函数,默认是什么都不做。如果override这个函数,就可以自定义消息处理。 }
dispatchMessage是Handler通用的消息处理函数
/** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) {//先看msg自己的callback函数,有就先执行,不再进行其他处理。 handleCallback(msg); } else { if (mCallback != null) {//再看Handler的Callback接口是否初始化,有就调用Callback接口的handleMessage处理消息。 if (mCallback.handleMessage(msg)) {//Callback接口的handleMessage处理后,返回为true就不在交给Handler的handleMessage处理 return; } } handleMessage(msg);//Handler自己的handleMessage处理 } }
通过上面的代码分析,可以知道如果Message对象注册了callback接口,就调用它的run处理消息。如果没有就先调用Handler里面定义的Callback接口的handleMessage处理。最后根据Callback接口的handleMessage处理结果,来看是否调用Handler自己的handleMessage。一般不会注册Message对象的callback接口,直接overrideHandler自己的handleMessage。
Handler对象必须绑定个Looper线程,一般是Activity的UI线程。
/** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ public Handler() { 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();//这里取主线程的Looper实例,一般是Activity的UI线程。 if (mLooper == null) {//没有Looper实例,就抛出异常,说明如果不提供Looper,主线程必须是Looper线程。 throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue;//取得Looper的实例,最重要的原因是,绑定Handler的消息队列。也就是说Handler实例,必须绑定一个可以执行消息处理的Looper线程。 mCallback = null; } /** * Constructor associates this handler with the queue for the * current thread and takes a callback interface in which you can handle * messages. */ public Handler(Callback callback) { 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; } /** * Use the provided queue instead of the default one. */ public Handler(Looper looper) { mLooper = looper;//这里直接给个Looper,说明主线程可以不为Looper,给个其他线程的Looper也行。 mQueue = looper.mQueue; mCallback = null; } /** * Use the provided queue instead of the default one and take a callback * interface in which to handle messages. */ public Handler(Looper looper, Callback callback) { mLooper = looper;//类似同上 mQueue = looper.mQueue;//类似同上 mCallback = callback; }
sendMessage去哪里了。其实就是加入到mQueue的消息队列中去了,也就是那个Looper线程的消息队列中。在加入消息队列的过程中,会唤醒Looper线程去处理消息。后续分析Looper时候详解。
/** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0);//调用sendMessageDelayed } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//如此调用,说明msg后面的参数是,生效时间。 } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue;//取出Looper线程的消息队列 if (queue != null) { msg.target = this;//消息的Handler指定为本Handler对象,为消息中sendToTarget方法指定Handler对象。也就是说如果Message对象如果注册了Handler对象,可以直接使用sendToTarget方法发送到Handler对象绑定的Looper线程处理。分析Message类的时候会讲解。 sent = queue.enqueueMessage(msg, uptimeMillis);//插入消息到Looper线程的消息队列。 } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }
post方法为什么传Runnable?从程序中可以看出,post函数先将Runnable赋值给Message对象,然后调用sendMessage函数发送消息。消息会在Looper对象中调用dispatchMessage方法来第一时间处理Runnable。
/** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0);//调用sendMessage系列函数,getPostMessage是生成一个post消息 } private static Message getPostMessage(Runnable r) { Message m = Message.obtain();//从消息pool中申请消息,pool满了,就new一个。 m.callback = r;//关键在这里,将Runnable接口赋给了callback接口,在dispatchMessage中先会处理callback接口。 return m; } public void dispatchMessage(Message msg) { if (msg.callback != null) {//先看msg自己的callback函数,有就先执行,不再进行其他处理。 handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
三、Looper源码分析:
路径:sdk\sources\android-16\android\os\Looper.java
重要函数分析:
Looper如何初始化?可以看到,Looper的构造函数是private的,就是说显示new不出Looper对象的,只能通过static 函数 myLooper得到。myLoopermyLoopermyLooper就返回nullActivity的UI线程
public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } private Looper(boolean quitAllowed) {//生成Looper实例 mQueue = new MessageQueue(quitAllowed); mRun = true; mThread = Thread.currentThread(); } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get();//获得当前线程的Looper对象 }
sThreadLocal对象是干什么用的?sThreadLocal对象是static的ThreadLocal<Looper>类型。ThreadLocal类是线程的本地存储,可以理解为一个简单的HashMap,key是ThreadLocal<T>对象,值是T对象。在Looper类中所有线程的key是唯一的ThreadLocal<Looper>对象,值为Looper对象。这里可以推出每个线程只能有一个Looper对象,而且线程如果有Looper对象,那么它们的key是相同的。这里不展开分析ThreadLocal类了,有机会再来详细分析它。
loop都在干些什么?loop函数首先获取当前线程的Looper对象,然后进入无限循环,从线程的消息队列中取消息。如果队列为空,就阻塞线程,直到有消息到来。只有在调用了quit函数后,消息队列才被清空,并返回一个null消息,退出无限循环。当有消息到来,取出消息,调用dispatchMessage函数处理消息,然后在回收消息。
/** * 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();//获取当前线程的Looper对象 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) {//只有当queue.quit调用后,条件才会成立。 // 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);//调用消息处理,一般是Handler对象的handleMessage来处理。 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.recycle();//回收消息对象 } } /** * Quits the looper. * * Causes the {@link #loop} method to terminate as soon as possible. */ public void quit() { mQueue.quit();//当消息队列允许退出时,此处退出循环,不允许时,会抛出异常。 }
三、Message源码分析:
路径:sdk\sources\android-16\android\os\Message.java
重要函数分析:
初始化尽然是obtain系列函数。Message的构造函数什么也不做,初始化工作基本上调用obtain。obtain一上来就查pool中是否有可分配消息,有就在pool中分配。没有才new一个消息。obtain系列都类似,以下列举部分。没什么好说的,一看就明白。/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); } public static Message obtain(Message orig) { Message m = obtain(); m.what = orig.what; m.arg1 = orig.arg1; m.arg2 = orig.arg2; m.obj = orig.obj; m.replyTo = orig.replyTo; if (orig.data != null) { m.data = new Bundle(orig.data); } m.target = orig.target; m.callback = orig.callback; return m; }
Message中函数比较容易理解,关键是它的成员变量挺有意思。接下来看看它的成员变量吧。
重要变量:
public int what;//指定消息类型,一般是自定义的消息。 public int arg1;//可用于消息参数或消息返回结果 public int arg2;//可用于消息参数或消息返回结果 public Object obj;//消息可携带的任何类型的对象,一般用做自定义数据类型。 public Messenger replyTo;//可以用消息回复消息。例如:一条命令消息的应答消息 Bundle data;//可以存放任何键值对,返回多个对象。 Handler target;//指定消息的处理对象 Runnable callback;//指定消息的Runnable方法
一般设计会使用到what来标识消息类型,arg1来做来源,arg2做目的,obj做传递的参数。target对象一般在初始化的时候会给出。如果需要传递多个对象作为参数会选择data来替换obj对象。callback是Handler对象post方法会使用到。replyto一般不会用到,特殊的情况下用消息回复消息时会用。