先粗略说一下Thread,Looper,MessageQueue,Message,Handler之间的基本关系:
1.一个Thread实例中会包含一个Looper实例
2.一个Looper实例中会包含一个MessageQueue实例
3.Handler把Message推送到MessageQueue内
4.Looper实例在Thread中处于死循环运行状态,负责不断的从MessageQueue中取出消息,取出消息后交给Handler处理
小结:Looper是运行在Thread实例中的,Message又是由Looper取出来交给Handler处理的,所以Handler处理Message的地方也是运行在Thread实例中的。
从ExampleThread.run中只看到了下面3步:
Looper.prepare();
internalHandler = new Handler()
Looper.loop();
难道只要这3步就把Handler处理Message的流程机制创建好了?
通过Looper的源码可以明白,通过调用Looper.prepare(),已经在当前Thread中创建了一个唯一的Looper实例,并且Looper实例持有的MessageQueue实例也已经创建好了。在当前线程中任何地方调用myLooper()都可以得到唯一的Looper实例。
Looper.prepare()分析完后继续分析internalHandler = new Handler()做了什么工作。
先上Handler的关键源码:
通过分析Handler的源码,在Handler的构造方法中获得了当前Thread中的Looper实例和Looper实例持有的MessageQueue实例。所以Handler已经和Looper,MessageQueue关联起来了,已经能够通过Handler向MessageQueue中推送消息了。
到目前为止就差处理MessageQueue中的Message了。也就差分析Looper.loop();了,这个loop方法在Looper的源码中已经写了详细的注释了。
所以仅需要在自定义线程中做完3步:
Looper.prepare();
internalHandler = new Handler()
Looper.loop();
就可以通过Handler往当前线程的MessageQueue中推送Message,然后当前线程中的Looper会从MessageQueue中依次取出Message来处理。
跟自定义Thread中run方法内的差不多,Looper.prepare()换成了Looper.prepareMainLooper(),其实还是同一个Looper实例,只是多了一个Looper.getMainLooper()。new Handler换成了ActivityThread.getHandler()。
上ActivityThread.getHandler()的源码:
所以UI主线程中的过程跟自定义线程是一样的。
1.一个Thread实例中会包含一个Looper实例
2.一个Looper实例中会包含一个MessageQueue实例
3.Handler把Message推送到MessageQueue内
4.Looper实例在Thread中处于死循环运行状态,负责不断的从MessageQueue中取出消息,取出消息后交给Handler处理
小结:Looper是运行在Thread实例中的,Message又是由Looper取出来交给Handler处理的,所以Handler处理Message的地方也是运行在Thread实例中的。
这个Thread实例有可能是UI主线程,也有可能是自定义线程 :)
Android开发中Handler处理Message分两种情况:
1.Handler在应用主线程中处理Message
2.Handler在自建的线程中处理Message
对于第1种情况先按下不表,等分析完第2种情况后再回过头来看第1种情况会容易很多。
对于第2种情况,开发情景一般如下面例子的代码,先上全部代码:
// 自定义类ExampleThread继承自Thread,内部Handler成员internalHandler
class ExampleThread extends Thread {
private static final String TAG = "ExampleThread";
private static final int MSG_WORK = 1;
private static final int MSG_PLAY_GAMES = 2;
private Handler internalHandler;
@Override
public void run() {
Looper.prepare();
synchronized (ExampleThread.this) {
internalHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_WORK:
Log.d(TAG, "I'm working");
break;
case MSG_PLAY_GAMES:
Log.d(TAG, "I'm playing games");
break;
default:
break;
}
}
};
ExampleThread.this.notifyAll();
}
Looper.loop();
}
public void goWork() {
while (internalHandler == null) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
internalHandler.sendEmptyMessage(MSG_WORK);
}
public void goPlayGames() {
while (internalHandler == null) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
Message msg = Message.obtain(internalHandler, MSG_PLAY_GAMES);
msg.sendToTarget();
}
}
// 测试代码,goWork和goPlayGames方法的实现都是通过internalHandler发送Message,internalHandler是在exampleThread线程内部处理Message
public void test() {
ExampleThread exampleThread = new ExampleThread();
exampleThread.start();
exampleThread.goWork();
exampleThread.goPlayGames();
}
从ExampleThread.run中只看到了下面3步:
Looper.prepare();
internalHandler = new Handler()
Looper.loop();
难道只要这3步就把Handler处理Message的流程机制创建好了?
那我们只能一步步来分析了。
先看Looper.prepare();做了些是什么,上Looper的关键源码:
package android.os;
public final class Looper {
private static final String TAG = "Looper";
/*ThreadLocal类用来提供线程内部的局部变量。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量*/
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
/*当所在线程为UI主线程时sMainLooper才会被使用到*/
private static Looper sMainLooper;
/*Looper持有的消息队列*/
final MessageQueue mQueue;
/*Looper所在线程的实例*/
final Thread mThread;
/*自定义线程调用此方法来prepare*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
/*如果sThreadLocal.get()不为null,则表示Looper已经prepare过了,不能重复prepare*/
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
/*调用Looper构造器创建一个Looper实例,并set进sThreadLocal。由于ThreadLocal的特性,在同一线程(当前线程)中我们通过sThreadLocal.get()得到的都是同一个Looper实例;而在不同线程中我们通过sThreadLocal.get()得到的又是不同的Looper实例。*/
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
/*创建一个消息队列*/
mQueue = new MessageQueue(quitAllowed);
/*获得当前线程的实例*/
mThread = Thread.currentThread();
}
/*UI主线程调用此方法来prepare*/
public static void prepareMainLooper() {
/*也是通过调用prepare来创建Looper实例*/
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
/*跟自定义线程不同的是把创建的Loooper实例赋给了sMainLooper引用*/
sMainLooper = myLooper();
}
}
/*其他进程要跟UI主线程IPC的话可以通过此方法获得主线程的Looper,然后向主线程发送事件,比如按键事件等*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
/*Looper开始工作*/
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
/*当前Looper持有的消息队列*/
final MessageQueue queue = me.mQueue;
for (;;) {
/*从消息队列中取出下一条Message,可能会阻塞*/
Message msg = queue.next();
if (msg == null) {
/*表示消息队列正在quitting*/
return;
}
/*取出来的Message交给target(即Handler,为什么target是Handler等后面Message源码部分再说)去调度处理*/
msg.target.dispatchMessage(msg);
/*Message处理完后释放资源*/
msg.recycleUnchecked();
}
}
/*prepare时把创建的Looper实例set进了sThreadLocal,所以在同一线程中myLooper方法得到的肯定是同一个Looper实例,所以一个Thread实例只有一个Looper实例*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
/*在Looper的构造器中创建了MessageQueue,由myLooper()性质决定了同一线程中myQueue方法得到的肯定也是同一个MessageQueue实例*/
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
/*判断是否在当前线程中。比如在线程A的代码中aLooper = myLooper()来获得线程A的Looper实例aLooper,然后可能在任何代码地方通过aLooper.isCurrentThread()来判断所在代码是否运行在线程A中*/
public boolean isCurrentThread() {
return Thread.currentThread() == mThread;
}
/*退出消息队列,当前消息队列中未被处理的消息将被丢弃。一旦调用quit后再向消息队列中推送消息就会失败,例如Handler.sendMessage(Message)会返回false*/
public void quit() {
mQueue.quit(false);
}
/*安全退出消息队列,当前消息队列中的消息都会被处理完。同样,一旦调用quit后再向消息队列中推送消息就会失败,例如Handler.sendMessage(Message)会返回false*/
public void quitSafely() {
mQueue.quit(true);
}
/*获得Looper实例中的当前线程实例*/
public @NonNull Thread getThread() {
return mThread;
}
/*获得Looper实例持有的消息队列,此方法为非静态方法,myQueue()为静态方法*/
public @NonNull MessageQueue getQueue() {
return mQueue;
}
}
通过Looper的源码可以明白,通过调用Looper.prepare(),已经在当前Thread中创建了一个唯一的Looper实例,并且Looper实例持有的MessageQueue实例也已经创建好了。在当前线程中任何地方调用myLooper()都可以得到唯一的Looper实例。
Looper.prepare()分析完后继续分析internalHandler = new Handler()做了什么工作。
先上Handler的关键源码:
package android.os;
public class Handler {
private static final String TAG = "Handler";
/*当前线程中的消息队列*/
final MessageQueue mQueue;
/*当前队列中的Looper*/
final Looper mLooper;
/*Handler的内部回调,Handler构造器中可以传入Callback,如果传入了此Callback,则Message将交给此Callback的handleMessage去处理,而不是交给Handler的handleMessage去处理*/
final Callback mCallback;
final boolean mAsynchronous;
public interface Callback {
public boolean handleMessage(Message msg);
}
/*Handler有很多构造器,无参构造器的话传入的Callback为null*/
public Handler() {
this(null, false);
}
public Handler(Callback callback) {
this(callback, false);
}
public Handler(boolean async) {
this(null, async);
}
public Handler(Callback callback, boolean async) {
/*获得当前线程中的Looper实例*/
mLooper = Looper.myLooper();
/*如果Looper实例为空,说明当前线程还没有调用Looper.prepare*/
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
/*获得当前线程中的消息队列*/
mQueue = mLooper.mQueue;
/*保存构造器传入的callback*/
mCallback = callback;
mAsynchronous = async;
}
/*向消息队列中推送一个Runnable,通过getPostMessage把Runnable封装成Message,调用sendMessageDelayed继续处理*/
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
/*Runnable封装成Message*/
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
/*Runnable实例成了Message的callback成员变量*/
m.callback = r;
return m;
}
/*向消息队列中推送一个Message,调用sendMessageDelayed继续处理*/
public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
/*sendMessageDelayed调用sendMessageAtTime继续处理*/
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
/*无论是向消息队列中推送Runnable还是Message,最后都走到了这个方法中*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
/*如果当前线程的消息队列为null,说明出了问题,推送会失败*/
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
/*把Message推送到消息队列中*/
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
/*把Message的target成员设置成了当前Handler。所以在Looper.loop()中的msg.target.dispatchMessage(msg);即调用了Handler的dispatchMessage*/
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
/*把Message压入队列*/
return queue.enqueueMessage(msg, uptimeMillis);
}
/*Looper.loop()中获得到待处理的Message后会调度到此处继续处理*/
public void dispatchMessage(Message msg) {
/*msg.callback在getPostMessage方法中赋值,msg.callback即为Runnable,如果Message成员中Runnable不为空则直接处理Runnable*/
if (msg.callback != null) {
handleCallback(msg);
} else {
/*mCallback在Handler构造器中赋值,如果有Callback就交给Callback来处理Message*/
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
/*最低优先级是由Handler的handleMessage来处理Message,子类一般会重载Handler的handleMessage*/
handleMessage(msg);
}
}
/*Message成员中Runnable的处理*/
private static void handleCallback(Message message) {
message.callback.run();
}
/*子类重载此方法来处理Message*/
public void handleMessage(Message msg) {
}
}
通过分析Handler的源码,在Handler的构造方法中获得了当前Thread中的Looper实例和Looper实例持有的MessageQueue实例。所以Handler已经和Looper,MessageQueue关联起来了,已经能够通过Handler向MessageQueue中推送消息了。
到目前为止就差处理MessageQueue中的Message了。也就差分析Looper.loop();了,这个loop方法在Looper的源码中已经写了详细的注释了。
所以仅需要在自定义线程中做完3步:
Looper.prepare();
internalHandler = new Handler()
Looper.loop();
就可以通过Handler往当前线程的MessageQueue中推送Message,然后当前线程中的Looper会从MessageQueue中依次取出Message来处理。
Handler在自定义线程中处理Message的情况分析完了,接着分析看看在UI主线程中Handler处理Message的机制是怎么搭建好的呢?
应用程序启动时会创建主线程,即ActivityThread,四大组件无论哪一个启动都是创建的ActivityThread。
上ActivityThread的main方法的源码:
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
跟自定义Thread中run方法内的差不多,Looper.prepare()换成了Looper.prepareMainLooper(),其实还是同一个Looper实例,只是多了一个Looper.getMainLooper()。new Handler换成了ActivityThread.getHandler()。
上ActivityThread.getHandler()的源码:
final Handler getHandler() {
return mH;
}
final H mH = new H();
private class H extends Handler {}
所以UI主线程中的过程跟自定义线程是一样的。