這是一篇淺入淺出的文章,對handler的使用和問題進行了一個總結,推薦看文章的你本身動手去練習,記憶和理解會更深入一點。java
咱們先看一下Handler的百科介紹:bash
Handler主要用於異步消息的處理:當發出一個消息以後,首先進入一個消息隊列,發送消息的函數即刻返回,而另一個部分在消息隊列中逐一將消息取出,
而後對消息進行處理,也就是發送消息和接收消息不是同步的處理。 這種機制一般用來處理相對耗時比較長的操做。
複製代碼
比較難明白,咱們先將概念拆分開理解,放下前面關於消息的部分,先着重看最後一句:處理相對耗時較長的操做。異步
在Android中,主線程中不能執行耗時操做,否則可能會形成ANR等問題,只能在子線程來進行。好比須要下載一個圖片並顯示到界面上,那麼直接按照邏輯,下載圖片是可能耗時的操做,新建一個線程執行下載,而後將下載的圖片傳入界面對應的視圖中,代碼以下:ide
new Thread(){
@Override
public void run() {
super.run();
final Bitmap bitmap = downloadImg();//下載圖片,返回bitmap
ivImg.setImageBitmap(bitmap);//傳入下載的圖片到視圖
}
};
複製代碼
邏輯是正確的,但操做不對,程序沒法運行。函數
由於在Android中,只有主線程能更新UI,因此主線程也叫UI線程,子線程中是不能更新UI的。這時候咱們就能夠用到Handler了,Handler能夠做爲Android更新UI的一套機制,正確的操做代碼以下:post
Handler handler = new Handler();
new Thread(){
@Override
public void run() {
super.run();
final Bitmap bitmap = downloadImg();//下載圖片,返回bitmap
handler.post(new Runnable() {
@Override
public void run() {
ivImg.setImageBitmap(bitmap);//經過Handler通知主線程更新UI
}
})
}
};
複製代碼
能夠看到,UI的操做放被到了Runnable對象中,而後利用Handler.post(Runnable)實現了UI的更新,能夠簡單理解Handler爲一個傳信者,將子線程中須要更新UI的信息傳入主線程中進行。spa
這是Handler的一種使用方法,經過post(Runnable),第二種是sendMessage()方式,示例以下:線程
mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if(msg==1){
tvText.setText("接收到消息,更改UI");//經過Handler通知主線程更新UI
}
return false;
}
});
new Thread() {
@Override
public void run() {
super.run()
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
}
}.start();
複製代碼
這裏能夠看到,Handler實現了消息的傳出、消息的接收與處理,其實在post(Runnable)方法中,Runnable對象自己也是做爲一個消息傳出的,再次回顧Handler的概念:code
Handler主要用於異步消息的處理:當發出一個消息以後,首先進入一個消息隊列,發送消息的函數即刻返回,而另一個部分在消息隊列中逐一將消息取出,
而後對消息進行處理,也就是發送消息和接收消息不是同步的處理。 這種機制一般用來處理相對耗時比較長的操做。
複製代碼
咱們知道了Handler是一個關於消息異步處理的任務機制,對於異步和同步,舉個例子說明對象
能夠看出,異步操做最大的特色是,不會阻礙調用者的工做,無需等待前一個操做作完才作下一個操做,對於耗時的操做,使用異步來處理是很是有必要的。
那麼在進行異步操做的過程當中,須要一個消息的傳遞者來指導各部分進行操做,在剛纔網購的例子裏,這個傳遞者是網上商城,而在Android的UI處理中,這個消息傳遞者就是Handler。
其餘一些Handler的使用方法
AsyncTask異步任務的使用
前面介紹了Handler+Thread進行異步消息處理,Android對此有封裝一個更好用的組件——AsyncTask。原理是相同的,但相比Handler+Thread更加簡單易用。
使用時首先須要構建AsyncTask子類的泛型參數,AsyncTask<Params,Progress,Result>是一個抽象類,一般用於被繼承,繼承AsyncTask須要指定以下三個泛型參數:
在構建AsyncTask子類主要有以下幾個回調方法: