Android应用中的消息循环由Looper和Handler配合完成,Looper类用于封装消息循环,类中有个MessageQueue消息队列;Handler类封装了消息投递和消息处理等功能。
系统默认情况下只有主线程(即UI线程)绑定Looper对象,因此在主线程中可以直接创建Handler的实例,但是在子线程中就不能直接new出Handler的实例了,因为子线程默认并没有Looper对象,此时会抛出RuntimeException异常:
浏览下Handler的默认构造函数就一目了然了:
1 public Handler() { 2 if (FIND_POTENTIAL_LEAKS) { 3 final Class<? extends Handler> klass = getClass(); 4 if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && 5 (klass.getModifiers() & Modifier.STATIC) == 0) { 6 Log.w(TAG, "The following Handler class should be static or leaks might occur: " + 7 klass.getCanonicalName()); 8 } 9 } 10 11 mLooper = Looper.myLooper(); 12 if (mLooper == null) { 13 throw new RuntimeException( 14 "Can't create handler inside thread that has not called Looper.prepare()"); 15 } 16 mQueue = mLooper.mQueue; 17 mCallback = null; 18 }
如果需要在子线程中使用Handler类,首先需要创建Looper类实例,这时可以通过Looper.prepare()和Looper.loop()函数来实现的。阅读Framework层源码发现,Android为我们提供了一个HandlerThread类,该类继承Thread类,并使用上面两个函数创建Looper对象,而且使用wait/notifyAll解决了多线程中子线程1获取子线程2的Looper对象为空的问题。HandlerThread类完整代码如下:
1 /** 2 * Handy class for starting a new thread that has a looper. The looper can then 3 * be used to create handler classes. Note that start() must still be called. 4 */ 5 public class HandlerThread extends Thread { 6 7 private int mPriority; // 线程优先级 8 9 private int mTid = -1; // 线程ID 10 11 private Looper mLooper; // 我们需要的Looper对象 12 13 public HandlerThread(String name) { 14 super(name); 15 mPriority = Process.THREAD_PRIORITY_DEFAULT; 16 } 17 18 /** 19 * Constructs a HandlerThread. 20 * 21 * @param name 22 * @param priority 23 * The priority to run the thread at. The value supplied must be 24 * from {@link android.os.Process} and not from java.lang.Thread. 25 */ 26 public HandlerThread(String name, int priority) { 27 super(name); 28 mPriority = priority; 29 } 30 31 /** 32 * 在Looper.loop()之前执行动作的回调函数 33 */ 34 protected void onLooperPrepared() { 35 } 36 37 public void run() { 38 mTid = Process.myTid(); 39 Looper.prepare(); // 创建本线程的Looper对象 40 41 synchronized (this) { 42 mLooper = Looper.myLooper(); 43 notifyAll(); //通知所有等待该线程Looper对象的其他子线程,本线程的Looper对象已就绪 44 } 45 46 Process.setThreadPriority(mPriority); 47 onLooperPrepared(); //回调函数 48 49 Looper.loop(); //开始消息队列循环 50 mTid = -1; 51 } 52 53 /** 54 * This method returns the Looper associated with this thread. If this 55 * thread not been started or for any reason is isAlive() returns false, 56 * this method will return null. If this thread has been started, this 57 * method will block until the looper has been initialized. 58 * 59 * @return The looper. 60 */ 61 public Looper getLooper() { 62 if (!isAlive()) { 63 return null; 64 } 65 66 // If the thread has been started, wait until the looper has been 67 // created. 68 synchronized (this) { 69 while (isAlive() && mLooper == null) { 70 try { 71 wait(); //Looper对象未创建好,等待 72 } catch (InterruptedException e) { 73 } 74 } 75 } 76 return mLooper; 77 } 78 79 /** 80 * Ask the currently running looper to quit. If the thread has not been 81 * started or has finished (that is if {@link #getLooper} returns null), 82 * then false is returned. Otherwise the looper is asked to quit and true is 83 * returned. 84 */ 85 public boolean quit() { 86 Looper looper = getLooper(); 87 if (looper != null) { 88 looper.quit(); 89 return true; 90 } 91 return false; 92 } 93 94 /** 95 * Returns the identifier of this thread. See Process.myTid(). 96 */ 97 public int getThreadId() { 98 return mTid; 99 } 100 }