官方描述:
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的線程。這個Looper能夠用來新建其他的Handler。(線程中的
Looper)需要注意的是,新建的時候需要被回調。
回顧普通用法
我們先來看看在使用HandlerThread之前使用Handler 和Thread的配合使用例子
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// 這裏處理消息
}
};
Looper.loop();
}
可以看到代碼很多很麻煩,google的工程師也注意到了這一點於是給我們封裝了一下,方便我們使用並且減少不必要的錯誤
基本使用用例
package com.example.double2.handlerthreadtest;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tvMain;
private HandlerThread mHandlerThread;
//子線程中的handler
private Handler mThreadHandler;
//UI線程中的handler
private Handler mMainHandler = new Handler();
//以防退出界面後Handler還在執行
private boolean isUpdateInfo;
//用以表示該handler的常熟
private static final int MSG_UPDATE_INFO = 0x110;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvMain = (TextView) findViewById(R.id.tv_main);
initThread();
}
private void initThread()
{
mHandlerThread = new HandlerThread("check-message-coming");
mHandlerThread.start();
mThreadHandler = new Handler(mHandlerThread.getLooper())
{
@Override
public void handleMessage(Message msg)
{
update();//模擬數據更新
if (isUpdateInfo)
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
};
}
private void update()
{
try
{
//模擬耗時
Thread.sleep(2000);
mMainHandler.post(new Runnable()
{
@Override
public void run()
{
String result = "每隔2秒更新一下數據:";
result += Math.random();
tvMain.setText(result);
}
});
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
@Override
protected void onResume()
{
super.onResume();
//開始查詢
isUpdateInfo = true;
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
@Override
protected void onPause()
{
super.onPause();
//停止查詢
//以防退出界面後Handler還在執行
isUpdateInfo = false;
mThreadHandler.removeMessages(MSG_UPDATE_INFO);
}
@Override
protected void onDestroy()
{
super.onDestroy();
//釋放資源
mHandlerThread.quit();
}
}
源碼介紹
HandlerThread的源碼非常的簡單看起來 so easy!
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
//也可以指定線程的優先級,注意使用的是 android.os.Process 而不是 java.lang.Thread 的優先級!
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
// 子類需要重寫的方法,在這裏做一些執行前的初始化工作
protected void onLooperPrepared() {
}
//獲取當前線程的 Looper
//如果線程不是正常運行的就返回 null
//如果線程啓動後,Looper 還沒創建,就 wait() 等待 創建 Looper 後 notify
public Looper getLooper() {
if (!isAlive()) {
return null;
}
synchronized (this) {
while (isAlive() && mLooper == null) { //循環等待
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
//調用 start() 後就會執行的 run()
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare(); //幫我們創建了 Looepr
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll(); //Looper 已經創建,喚醒阻塞在獲取 Looper 的線程
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop(); //開始循環
mTid = -1;
}
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;
}
public int getThreadId() {
return mTid;
}
}
注意點:
①HandlerThread 本質還是個 Thread,創建後別忘了調用 start()。
②在 run() 方法中創建了 Looper,調用 onLooperPrepared 後開啓了循環
③我們要做的就是在子類中重寫 onLooperPrepared,做一些初始化工作
④在創建 HandlerThread 時可以指定優先級,注意這裏的參數是 Process.XXX 而不是 Thread.XXX