在Android的异步消息处理机制中,Handler发挥着重要的作用,本文从Handler源码的角度,对Handler的使用进行分析。首先来看看Handler的创建方式:
1. 在主线程可以直接通过new创建
2. 在子线程中需要先调用Looper.prepare(),再执行new操作,否则会崩溃提示:
Can't create handler inside thread that has not called Looper.prepare()
那么问题来了,为什么在子线程中不调用Looper.prepare()就会崩溃?为什么在主线程中可以直接new创建?我们先看看Handler的构造方法:
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时,当前的线程必须要有Looper,其Looper对象存放在sThreadLocal对象中,我们可以猜测是Looper.prepare()调用时创建和存放,接着看Looper.prepare():
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
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));
}
可知,就像我们猜测的那样,的确是prepare()时创建Looper对象,然后存放到sThreadLocal中,并且一个线程只能有一个Looper对象。
至此第一个问题得解,我们来看第二个问题:为什么在主线程中直接new就不会崩溃?通过函数的引用关系,可以看到调用private static void prepare(boolean quitAllowed)的除了public static void prepare(),还有public static void prepareMainLooper(),其具体实现如下:
/**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
可见,在prepareMainLooper()中调用了prepare()。我们接着看prepareMainLooper()的引用关系,可以找到在ActivityThread的main()方法中调用了,如下:
public static void main(String[] args) {
......
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
ActivityThread作为App的入口,在App启动时其main()方法会调用,当然就会执行prepareMainLooper(),
由此可知系统已经已经为主线程创建了Looper对象,所以我们可以直接通过new操作创建对象。