请支持原创~~
版本基于:Android R
前言:
Android 基于Handler 剖析消息机制 中剖析了Handler为基础的消息通信机制, Android 中Handler 详解 中大体说了一下handler的应用过程,android 提供了HandlerThread,更好的可以为多线程的应用场景服务。
比较 Android AsyncTask 详解 ,HandlerThread 提供了长期的Thread,支持各种消息传递、处理,而无需像AsyncTask 每次都需要重新创建、execute。
源码解析:
/**
* A {@link Thread} that has a {@link Looper}.
* The {@link Looper} can then be used to create {@link Handler}s.
* <p>
* Note that just like with a regular {@link Thread}, {@link #start()} must still be called.
*/
通过注释可以看出:
- HandlerThread 是一个拥有自己Looper 的Thread;
- HandlerThread 可以通过Looper创建Handler,用以msg 的发送和处理;
- HandlerThread 是个Thread,执行时需要先调用start();
构造:
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
Thread 的priority 可以外面指定,也可以使用默认优先级,默认优先级值为0;
start():
HandlerThread 在使用的时候需要调用start函数,用以完成初始化工作。
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
getLooper():
在新建实例之后,必须要start 才能能应用,不然在getLooper的时候:
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;
}
会认为不是alive,返回null。
所以一般应用过程是这样的:
//创建一个HandlerThread,即创建了一个包含Looper的线程。
HandlerThread handlerThread = new HandlerThread("leochin.com");
handlerThread.start(); //创建HandlerThread后一定要记得start()
//获取HandlerThread的Looper
Looper looper = handlerThread.getLooper();
//创建Handler,通过Looper初始化
Handler handler = new Handler(looper);
quit 和 quitSafely:
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
- safe 模式下会判断将没有处理的msg recycle掉,已经在处理的,会等到处理完成;
- 非safe模式下则不会check,直接全部recycle 掉;
举例
(copy 于Android TV):
public TvInputBaseSession(Context context, String inputId, int deviceId) {
super(context);
mInputId = inputId;
mDeviceId = deviceId;
mTvInputManager = (TvInputManager)context.getSystemService(Context.TV_INPUT_SERVICE);
mHardware = mTvInputManager.acquireTvInputHardware(deviceId,
mHardwareCallback, mTvInputManager.getTvInputInfo(inputId));
initThread(mInputId);
}
private void initThread(String inputId) {
mHandlerThread = new HandlerThread(inputId);
mHandlerThread.start();
mSessionHandler = new Handler(mHandlerThread.getLooper(), this);
}
private void releaseThread() {
mHandlerThread.quit();
mHandlerThread = null;
mSessionHandler = null;
}
@Override
public boolean handleMessage(Message msg) {
if (DEBUG)
Log.d(TAG, "==== handleMessage ====" + msg.what);
switch (msg.what) {
case DroidLogicTvUtils.SESSION_DO_RELEASE:
doRelease();
break;
default:
break;
}
return false;
}
public void doRelease() {
mHardware.setSurface(null, null);
mTvInputManager.releaseTvInputHardware(mDeviceId, mHardware);
releaseThread();
}
@Override
public void onRelease() {
mSessionHandler.obtainMessage(DroidLogicTvUtils.SESSION_DO_RELEASE).sendToTarget();
}
在initThread 函数中,构造完HandlerThread 后会调用start,初始化Looper。接着通过getLooper 创建一个Handler进行通信使用。
Android TV 中要求有些操作时间不能过长,例如onRelease,通过这样的操作就成功避免了
至此,HandlerThread 的源码基本分析完成。总结:
- HandlerThread 是一个拥有自己Looper 的Thread;
- HandlerThread 可以通过Looper创建Handler,用以msg 的发送和处理;
- HandlerThread 是个Thread,执行时需要先调用start();
- quit 分safe 和非safe 模式;