Looper是Handler运行的重要组成部分,UI线程系统自动创建了Looper并提供了自动的启动和停止工作,但普通线程则需要手动创建,而HandlerThread就是系统提供的一种创建带有Looper的Thread的方案,比起Thread+Handler更加灵活和安全。
package android.os; /** * Handy class for starting a new thread that has a looper. The looper can then be * used to create handler classes. Note that start() must still be called. HandlerThread是带有Looper的Thread,在创建Handler时在构造器中使用handlerThread.getLooper()获取这个线程的looper给handler实例,就可以使用这个线程处理handler发送的消息了 */ public class HandlerThread extends Thread { int mPriority; int mTid = -1; Looper mLooper; public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } /** * Constructs a HandlerThread. * @param name * @param priority The priority to run the thread at. The value supplied must be from * {@link android.os.Process} and not from java.lang.Thread. */ public HandlerThread(String name, int priority) { super(name); mPriority = priority; } /** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() { } @Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; } /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } /** * Quits the handler thread's looper. * <p> * Causes the handler thread's looper to terminate without processing any * more messages in the message queue. * </p><p> * Any attempt to post messages to the queue after the looper is asked to quit will fail. * For example, the {@link Handler#sendMessage(Message)} method will return false. * </p><p class="note"> * Using this method may be unsafe because some messages may not be delivered * before the looper terminates. Consider using {@link #quitSafely} instead to ensure * that all pending work is completed in an orderly manner. * </p> * * @return True if the looper looper has been asked to quit or false if the * thread had not yet started running. * * @see #quitSafely * 线程的looper直接关闭,message queue不再处理和接受消息 */ public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } /** * Quits the handler thread's looper safely. * <p> * Causes the handler thread's looper to terminate as soon as all remaining messages * in the message queue that are already due to be delivered have been handled. * Pending delayed messages with due times in the future will not be delivered. * </p><p> * Any attempt to post messages to the queue after the looper is asked to quit will fail. * For example, the {@link Handler#sendMessage(Message)} method will return false. * </p><p> * If the thread has not been started or has finished (that is if * {@link #getLooper} returns null), then false is returned. * Otherwise the looper is asked to quit and true is returned. * </p> * * @return True if the looper looper has been asked to quit or false if the * thread had not yet started running. * 线程的looper会等到已在消息队列中的消息被取出后关闭,延时消息不再 * 处理,不再接受任何消息 */ public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; } /** * Returns the identifier of this thread. See Process.myTid(). */ public int getThreadId() { return mTid; } } HandlerThread源码分析
使用HandlerThread的简单代码
public class MainActivity extends AppCompatActivity { private HandlerThread mHandlerThread; private Handler mThreadHandler; @Override protected void onCreate(Bundle savedInstanceState) { ... initThread(); } private void initThread() { mHandlerThread = new HandlerThread("thread-name"); mHandlerThread.start(); mThreadHandler = new Handler(mHandlerThread.getLooper()) { @Override public void handleMessage(Message msg) { update(); } }; } private void update() { try { //模拟耗时 Thread.sleep(2000); //完成后通知主线程 主线程Handler.post()/sendXXMessage() } catch (InterruptedException e) { e.printStackTrace(); } } @Override protected void onResume() { super.onResume(); //发送消息给该子线程,让其处理一段任务 mThreadHandler.sendEmptyMessage("some-message"); } @Override protected void onDestroy() { super.onDestroy(); //不用该线程时需要手动停止Looper mHandlerThread.quitSafely(); } }
总结
HandlerThread就是内部建立了looper工作机制的Thread。
用处
1.在UI线程中,无论是更新UI,还是执行其他异步任务,都会用到MainLooper,为了降低MainLooper的负载,提高UI线程的性能,就出现了拥有looper的子线程。因为拥有自己的消息队列,他也不会干扰或阻塞主线程。
2.用于线程间通信,比如一个子线程发送消息到另一个子线程处理。
注意
1.HandlerThread是一个线程,当处理消息时,也是一个一个拿出来顺序处理的,所以如果一个消息处理较为耗时,下一个消息也只能一直等待,所以需要注意这种后续任务的等待是否会影响到性能。
2.关闭线程只需要结束run()方法,所以需要接束在run()中死循环的loop()方法,故需要条用quit()或quitSafely()。