Android中的Thread没有对java中的Thread做任何封装,而Android提供了一个遍历方法HandlerThread,他继承于Thread,实现了对遍历系统的一些封装,下面研究一下HandlerThread的源码:
1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os; 18 19 /** 20 * Handy class for starting a new thread that has a looper. The looper can then be 21 * used to create handler classes. Note that start() must still be called. 22 */ 23 public class HandlerThread extends Thread { 24 int mPriority; 25 int mTid = -1; 26 Looper mLooper; 27 28 public HandlerThread(String name) { 29 super(name); 30 mPriority = Process.THREAD_PRIORITY_DEFAULT; 31 } 32 33 /** 34 * Constructs a HandlerThread. 35 * @param name 36 * @param priority The priority to run the thread at. The value supplied must be from 37 * {@link android.os.Process} and not from java.lang.Thread. 38 */ 39 public HandlerThread(String name, int priority) { 40 super(name); 41 mPriority = priority; 42 } 43 44 /** 45 * Call back method that can be explicitly overridden if needed to execute some 46 * setup before Looper loops. 47 */ 48 protected void onLooperPrepared() { 49 } 50 51 @Override 52 public void run() { 53 mTid = Process.myTid(); 54 Looper.prepare(); 55 synchronized (this) { 56 mLooper = Looper.myLooper(); 57 notifyAll(); 58 } 59 Process.setThreadPriority(mPriority); 60 onLooperPrepared(); 61 Looper.loop(); 62 mTid = -1; 63 } 64 65 /** 66 * This method returns the Looper associated with this thread. If this thread not been started 67 * or for any reason is isAlive() returns false, this method will return null. If this thread 68 * has been started, this method will block until the looper has been initialized. 69 * @return The looper. 70 */ 71 public Looper getLooper() { 72 if (!isAlive()) { 73 return null; 74 } 75 76 // If the thread has been started, wait until the looper has been created. 77 synchronized (this) { 78 while (isAlive() && mLooper == null) { 79 try { 80 wait(); 81 } catch (InterruptedException e) { 82 } 83 } 84 } 85 return mLooper; 86 } 87 88 /** 89 * Quits the handler thread's looper. 90 * <p> 91 * Causes the handler thread's looper to terminate without processing any 92 * more messages in the message queue. 93 * </p><p> 94 * Any attempt to post messages to the queue after the looper is asked to quit will fail. 95 * For example, the {@link Handler#sendMessage(Message)} method will return false. 96 * </p><p class="note"> 97 * Using this method may be unsafe because some messages may not be delivered 98 * before the looper terminates. Consider using {@link #quitSafely} instead to ensure 99 * that all pending work is completed in an orderly manner. 100 * </p> 101 * 102 * @return True if the looper looper has been asked to quit or false if the 103 * thread had not yet started running. 104 * 105 * @see #quitSafely 106 */ 107 public boolean quit() { 108 Looper looper = getLooper(); 109 if (looper != null) { 110 looper.quit(); 111 return true; 112 } 113 return false; 114 } 115 116 /** 117 * Quits the handler thread's looper safely. 118 * <p> 119 * Causes the handler thread's looper to terminate as soon as all remaining messages 120 * in the message queue that are already due to be delivered have been handled. 121 * Pending delayed messages with due times in the future will not be delivered. 122 * </p><p> 123 * Any attempt to post messages to the queue after the looper is asked to quit will fail. 124 * For example, the {@link Handler#sendMessage(Message)} method will return false. 125 * </p><p> 126 * If the thread has not been started or has finished (that is if 127 * {@link #getLooper} returns null), then false is returned. 128 * Otherwise the looper is asked to quit and true is returned. 129 * </p> 130 * 131 * @return True if the looper looper has been asked to quit or false if the 132 * thread had not yet started running. 133 */ 134 public boolean quitSafely() { 135 Looper looper = getLooper(); 136 if (looper != null) { 137 looper.quitSafely(); 138 return true; 139 } 140 return false; 141 } 142 143 /** 144 * Returns the identifier of this thread. See Process.myTid(). 145 */ 146 public int getThreadId() { 147 return mTid; 148 } 149 }
下面来分析一下该类的实现原理:
1、首先该类有两个构造方法:一个传入一个字符串名称,任意选取,优先级设置为默认的,第二个多了设置进程优先级的参数
2、
实际上简单理解就是:HandlerThread可以让Handler运行于其他线程中,在平常应用中,以Activity为例,新建一个Handler对象,默认是运行于UI线程中的,如果需要在Handler中执行一些耗时的任务,可以重新开启一个子线程来执行,而不可以直接在handler中执行;
那具体用途在于哪呢?
如果需要在子线程中使用Handler类,首先需要创建Looper类实例,这时可以通过Looper.prepare()和Looper.loop()函数来实现的。阅读Framework层源码发现,Android为我们提供了一个HandlerThread类,该类继承Thread类,并使用上面两个函数创建Looper对象,而且使用wait/notifyAll解决了多线程中子线程1获取子线程2的Looper对象为空的问题
为了方便描述,这里附上一段demo:
1 void useHanlerThread() { 2 3 // two ways to construct HandlerThread 4 HandlerThread hThread = new HandlerThread(”AnyName“, 5 6 // a property in android.os.Process 7 Process.THREAD_PRIORITY_BACKGROUND); 8 9 // HandlerThread hThread2 = new HandlerThread(”AnyName“); 10 hThread.start(); 11 12 // get Looper object of hThread(HandlerThread) 13 Looper looper = hThread.getLooper(); 14 15 Handler h = new Handler(looper) { 16 @Override 17 public void handleMessage(Message msg) { 18 // TODO Auto-generated method stub 19 super.handleMessage(msg); 20 } 21 }; 22 23 }
由上面代码第4行可以看到,这里采用HandlerThread新建一个thread对象,实际上他就是一个Thread,只不过经过了一些封装,它封装了looper等,所以该实例也就是一个worker thread,也即新建了一个线程,只是不需要维护Looper,内部封装好了,当调用HandlerThread的start方法时,就会执行重写的run方法,进而可以直接通过第13行代码的getLooper获取,然后根据获取的这个looper来实例化Handler,这样这个Handler就工作于前面创建的HandlerThread实例中,也就是说相比传统的方式,这里可以直接处理耗时逻辑而无需再新建线程
这里再附上一段样例代码来辅助理解:
1 public void startWorkerHandler(){ 2 HandlerThread handlerThread = new HandlerThread("handler-thread"); 3 handlerThread.start(); 4 5 final Handler handler = new Handler(handlerThread.getLooper()); 6 handler.post(new Runnable() { 7 @Override 8 public void run() { 9 10 npb.increaseProgressBy(1); 11 handler.postDelayed(this, 100); 12 } 13 }); 14 }
实例:
1 package com.example.randy.helloworld; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.HandlerThread; 7 import android.os.Looper; 8 9 /** 10 * Created by randy on 2015/12/7. 11 */ 12 public class HandlerDemo extends Activity { 13 private Handler handler1; 14 15 private Handler handler2; 16 17 private HandlerThread handlerThread; 18 private Handler handler3; 19 20 @Override 21 protected void onCreate(Bundle savedInstanceState) { 22 super.onCreate(savedInstanceState); 23 setContentView(R.layout.activity_main); 24 handler1 = new Handler(); 25 new Thread(new Runnable() { 26 @Override 27 public void run() { 28 Looper.prepare(); 29 handler2 = new Handler(); 30 Looper.loop(); 31 } 32 }).start(); 33 34 /* new Thread(new Runnable(){ 35 @Override 36 public void run(){ 37 handlerThread = new HandlerThread("handlerThread"); 38 handlerThread.start(); 39 } 40 }).start();*/ 41 42 new HandlerThread("handlerThread"){ 43 44 @Override 45 public void run(){ 46 47 handler3 = new Handler(); 48 } 49 }.start(); 50 } 51 }