Android Handler的使用方式和注意事項

2021-09-11 12:58:40 字數 4687 閱讀 3386

//在主線程建立乙個handler物件。

//重寫handler的handlemessage方法,這個就是接收並處理訊息的方法。

handler handler = new handler()

};//開啟乙個子執行緒

new thread(new runnable()

}).start();複製**

上面就是乙個簡單的handler使用例子。我們在主線程建立乙個handler,他的handlemessage()方法是執行在主線程的,當我們在子執行緒傳送乙個訊息的時候,handlemessage()會接收到訊息,這樣我們就把訊息由子執行緒傳送到了主線程。上面的**中,handler傳送的訊息是乙個空訊息,什麼資料也沒有,如果我們只是單純的傳送乙個空訊息,可以使用handler自己的傳送空訊息的方法:

handler.sendemptymessage(what);複製**
這兩種傳送空訊息的效果是一樣的。至於這裡的what是什麼我們後面會說到。

handler也可以傳送帶有資料的訊息。message物件有乙個object型別的obj屬性,就是用來攜帶訊息資料的。我們只需要把要傳送的資料賦值給obj就可以了,然後在處理訊息的時候再把資料取出來。

handler handler = new handler()

};new thread(new runnable()

}).start();複製**

上面的**中,msg攜帶乙個字串資料:"我是訊息資料",在handlemessage()方法中把這個資料取出來。除了obj以外,message還有兩個int型別的屬性:arg1、arg2可以用來傳送一些簡單的資料。

現在我們看到的所有的訊息都是在handler的handlemessage()方法中處理,如果我要傳送很多個訊息,每個訊息的資料都不一樣,訊息的處理邏輯也不一樣,那麼在handlemessage()方法中如何去判斷哪個訊息是哪個呢?這時message的what屬性就派上用場了,what屬性就是上面傳送空訊息時我們看到的what,它是一int型別,它是用來標識訊息的。

handler handler = new handler() }};

new thread(new runnable()

}).start();複製**

上面我們在子執行緒中傳送了兩個訊息,並且給兩個訊息設定了它的what,在處理訊息的時候就可以通過msg的what來判斷是哪個訊息了。

除了用sendmessage傳送message訊息以外,handler還可以post乙個runnable。

new thread(new runnable() 

});}

}).start();複製**

其實post()方法和sendmessage()方法的邏輯是一樣的,post()方法中的runnable會被封裝成message,然後傳送出去。下面看它的原始碼:

public

final

boolean

post

(runnable r)

private

static message getpostmessage

(runnable r)

複製**

//宣告handler;

handler handler;

new thread(new runnable()

};//開啟looper的訊息輪詢

looper.loop();

}}).start();

mbanner.setonclicklistener(new view.onclicklistener()

});複製**

在上面的例子中,我們在子執行緒建立handler物件,handler的looper就是子執行緒的looper,所以訊息的處理也就是在子執行緒處理的。這就是在子執行緒使用handler的方式。在這裡有幾個需要注意的點:(很重要)

1、在子執行緒使用handler前一定要先為子執行緒建立looper,建立的方式是直接呼叫looper.prepare()方法。前面我們說過建立handler物件時如果沒有給它指定looper,那麼它缺省會使用當前執行緒的looper,而執行緒預設是沒有looper的,所以使用前一定要先建立looper。

2、在同乙個執行緒裡,looper.prepare()方法不能被呼叫兩次。因為同乙個執行緒裡,最多只能有乙個looper物件。

3、只有呼叫了looper.loop()方法,handler機制才能正常工作。looper負責管理messagequeue,它的loop()方法負責從messagequeue裡取出訊息並交給handler處理,所以如果沒有呼叫looper.loop()方法,訊息就不會被取出和處理。

4、looper.loop()方法一定要在呼叫了looper.prepare()方法之後呼叫。那是因為如果當前執行緒還沒有looper,是不能呼叫looper.loop()方法開啟訊息輪詢的,否則會報錯。

5、不要在主線程呼叫looper.prepare()方法。這是因為在android系統建立主線程的時候就已經呼叫了looper.prepare()方法和looper.loop()方法,這也是為什麼我們在主線程使用handler時不需要呼叫這兩個方法的原因。

6、當我們在子執行緒使用handler時,如果handler不再需要傳送和處理訊息,那麼一定要退出子執行緒的訊息輪詢。因為looper.loop()方法裡是乙個死迴圈,如果我們不主動結束它,那麼它就會一直執行,子執行緒也會一直執行而不會結束。退出訊息輪詢的方法是:

looper.mylooper().quit();

looper.mylooper().quitsafely();複製**

上面的例子都是用執行緒自己的looper來建立handler,我們也可以用指定的looper來建立handler。

new thread(new runnable() };}

}).start();複製**

上面的例子中,我們雖然是在子線建立handler,但因為用的是主線程的looper,所以訊息的處理是在主線程的,這跟在主線程建立handler是一樣的。因為這裡並沒有使用到子執行緒的looper,所以不要呼叫looper.prepare()和looper.loop()方法。

以上我們所說的是handler切換執行緒的使用。handler除了提供post()方法和sendmessage()方法以外,還提供了一系列的傳送訊息的方法。比如延時傳送訊息和定時傳送訊息:

//延時傳送訊息

public

final

boolean

sendmessagedelayed

(message msg, long delaymillis)

public

final

boolean

postdelayed

(runnable r, long delaymillis)

; //定時傳送訊息

public

boolean

sendmessageattime

(message msg, long uptimemillis)

},1000);複製**

上面的例子並沒有涉及到執行緒的切換,只是利用了handler延時傳送訊息的功能達到延時列印。所以handler的使用不僅僅是切換執行緒。更多的方法使用就不一一舉例了。

小知識點:

1、使用message.obtain()來獲取乙個訊息。前面我們的例子中獲取乙個訊息都是用new的方式直接建立,我這樣做只是為了方便大家的理解而已。在使用中不推薦用這種方式來獲取乙個訊息,而是使用message.obtain()方法。

message msg = message.obtain();複製**
android會為message提供乙個快取池,把使用過的訊息快取起來,方便下次使用。我們用message.obtain()方法獲取乙個訊息時,會先從快取池獲取,如果快取池沒有訊息,才會去建立訊息。這樣做可以優化記憶體。

2、同乙個message不要傳送兩次。如下面的**是有問題的:

//同乙個message傳送了兩次

message msg = message.obtain();

handler.sendmessage(msg);

handler.sendmessage(msg);複製**

這是因為所以的訊息都是傳送到messagequeue存放,然後等待處理的。如果乙個message物件在messagequeue裡,再次把它存到messagequeue時就會報錯。

3、android已經提供了很多實現了handler的類和方法,方便我們使用。如activity類的runonuithread()方法,view的post()方法,handlerthread類等,關於這些知識,大家可以查閱相關資料,這裡就不做講解了,因為他們的實現其實跟我們前面說的是一樣的。

文章已同步到我的csdn部落格:blog.csdn.net/u010177022/…

Android Handler訊息機制

handler訊息機制 優點 寫法 1.主線程中建立乙個handler物件 handler handler new handler 2.複寫handler物件的handlermessage方法 public void handlemessage android.os.message msg 3.在子...

Android Handler 工作原理

handler message messagequeue looper 1.looper.prepare public static void prepare private static void prepare boolean quitallowed 這裡建立的looper sthreadloc...

Android Handler相關問題

1 handler是什麼?答 handler是更新ui介面的機制,也是訊息處理的機制,我們可以傳送訊息,也可以處理訊息 2 為什麼要有handler?答 android在設計的時候,封裝了一套訊息建立 傳遞 處理機制,如果不遵循這樣的機制就沒辦法更新ui資訊,就會丟擲異常。3 handler怎麼用?...