Android提供了一個非同步訊息回調機制Handler, 它負責發送訊息和處理線程訊息佇列中的訊息及runnable對象
Handler執行個體都是與一個線程和該線程的訊息佇列一起使用,一旦建立了一個新的handler執行個體,系統就把該執行個體與一個線程和該線程的訊息佇列捆綁起來,這將可以發送訊息和runnable對象給該訊息佇列,並在訊息佇列出口處處理它們。
Handler預設使用當前的線程RunLoop, 但是也可以通過它的建構函式來指定某個線程的runloop, 或者使用專用的HandlerThread。
必須要注意的是, 使用Handler的線程中,必須實現了Runloop訊息迴圈,否則會產生運行異常。
通常情況下,如果我們在主線程使用Handler, 則不需要我們主動去建立runloop, 因為android系統為自動為activity主線程建立一個runloop。
同樣我們可以在一個特殊的子線程中使用Handler,而不必去建立runloop。這個特殊子線程就是HandlerThread, 查看其源碼,我們可以發現,它也在run方法中實現了runloop。
下面就介紹Handler的幾種使用情境和用法:
1. 在主線程中使用Handler
主線程中使用Handler相對簡單, 下面的範例程式碼實現了在主線程中建立Handler對象,啟動一個runable方法去重新整理進度條。代碼如下:
[java]
//在主線程中建立一個Handler對象
//在主線程中建立一個Handler對象[java] view plaincopyprint? Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
firBar.setProgress(msg.arg1);
handler.post(updateThread);
Log.v("thread----", Thread.currentThread().getName());
}
};
Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
firBar.setProgress(msg.arg1);
handler.post(updateThread);
Log.v("thread----", Thread.currentThread().getName());
}
};[java] view plaincopyprint?<SPAN style="WHITE-SPACE: pre"> handler.post(updateThread);</SPAN> //去運行
handler.post(updateThread); //去運行
[java]
//建立一個runable去重新整理進度條
//建立一個runable去重新整理進度條[java] view plaincopyprint? Runnable updateThread = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
if ( i>= 100) {
handler.removeCallbacks(updateThread);
return;
}
i += 10;
Message msg = handler.obtainMessage();
msg.arg1 = i;
try {
Thread.sleep(1000); //線程暫停1s
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
handler.sendMessage(msg);
handler1.sendEmptyMessage(0);
}
};
Runnable updateThread = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
if ( i>= 100) {
handler.removeCallbacks(updateThread);
return;
}
i += 10;
Message msg = handler.obtainMessage();
msg.arg1 = i;
try {
Thread.sleep(1000); //線程暫停1s
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
handler.sendMessage(msg);
handler1.sendEmptyMessage(0);
}
};
2. 在普通的子線程中使用Handler
範例程式碼如下:
[java]
//建立一個子線程,在其中使用Handler
class MyThread extends Thread
{
public void run() {
Looper.prepare();
handler1 = new Handler()//Looper.getMainLooper()
{
public void handleMessage(Message msg)
{
Log.v("SubThread",Thread.currentThread().getName());
// 這裡執行耗時操作,不會影響到UI主線程
for (int i = 0; i < 1000000000; i++) {
}
}
};
Looper.loop();
}
}
//建立一個子線程,在其中使用Handler
class MyThread extends Thread
{
public void run() {
Looper.prepare();
handler1 = new Handler()//Looper.getMainLooper()
{
public void handleMessage(Message msg)
{
Log.v("SubThread",Thread.currentThread().getName());
// 這裡執行耗時操作,不會影響到UI主線程
for (int i = 0; i < 1000000000; i++) {
}
}
};
Looper.loop();
}
}
3. 在HandlerThread線程中使用Handler
[java]
HandlerThread handlerThread = new HandlerThread("handlerThread");
handlerThread.start();
//這裡擷取到HandlerThread的runloop
MyHandler myHandler = new MyHandler(handlerThread.getLooper());
HandlerThread handlerThread = new HandlerThread("handlerThread");
handlerThread.start();
//這裡擷取到HandlerThread的runloop
MyHandler myHandler = new MyHandler(handlerThread.getLooper());