天天看點

Android線程和線程Handler基礎一覽

線程概覽

線程是任何多任務系統的基石。可以被認為是一個主程序的多個子程序。這樣做的目的就是了增加應用的性能。

應用主線程

當一個android應用被打開的時候,系統會預設開辟一個線程。這個線程就被叫做是主線程。主線程的主要任務就是處理使用者輸入,即事件處理和view上的使用者互動。任何應用裡的其他元件,預設的,都是在主線程中運作的。

一個應用的任何元件,如果在主線程上執行一個耗時的任務的話,都會使整個應用等待這個任務的完成。如果耗時過長的話就會觸發系統的“application is unresponsive”警告。顯然,這個是任何應用都不願意出現的狀況。在這種情況下,隻能開辟一個單獨的線程來執行這個耗時的任務,這樣才不會幹擾主線程上的其他任務。

線程handler

是以,應用開發中最關鍵的一條就是永遠不要在主線程上執行耗時過長的任務。另外一個同樣重要的規則是另外開辟的單獨的線程任何情況下、絕對不可以直接更新使用者界面。任何對使用者界面的更新都要在主線程中進行。之是以這樣的原因是android的ui不是線程安全的。在多線程環境下調用非線程安全的代碼會導緻斷斷續續的問題以及不可預料的應用行為。

要在子線程中更新使用者界面就隻能通過handler來實作。

一個簡單的thread例子

這裡會提供幾個簡單的例子來展示線程和handler是如何使用的。第一步,展示一下耗時任務沒有放在另外開辟的線程中,而放在主線程中出現的問題。首先建立一個android項目叫做“threadexample”,包含一個單獨的空白的activity:threadexampleactivity,layout叫做activity_thread_example。

具體的布局檔案如下:

Android線程和線程Handler基礎一覽
Android線程和線程Handler基礎一覽

看起來是這樣的:

Android線程和線程Handler基礎一覽

儲存。接下來,輕按兩下threadexampleactivity.java進入編輯模式。在這個activity檔案中實作button的click方法。這個方法會在使用者點選按鈕之後被調用。這裡主要是展示耗時任務的問題,是以會在主線程中發起一個20秒的延遲,之後更新textview對象的文字。

代碼如下:

Android線程和線程Handler基礎一覽
Android線程和線程Handler基礎一覽

以上代價在運作之後,點選一下按鈕,這個時候整個應用就在20秒的等待中。再次或者多次點選這個按鈕不會立刻有反應。這時候系統就會彈出一個提醒:應用正在忙:

Android線程和線程Handler基礎一覽

是以,在按鈕點選方法中,耗時的操作應該放置在另外一個單獨的線程中。

建立一個新的線程

要建立一個新的線程,并讓代碼在這個線程中執行,需要把這些代碼都放在runnable接口的run中。然後需要建立一個新的thread對象。把runnable接口的執行個體作為參數傳給thread的構造函數中。最後調用thread執行個體的start方法來開辟線程并執行線程中的方法。

修改後的代碼如下:

Android線程和線程Handler基礎一覽
Android線程和線程Handler基礎一覽

當應用再次運作起來之後。點選按鈕之後把造成延時的任務都放在了新的線程中運作,主線程可以及時響應使用者的任何操作,包括無休止的按鈕點選。事實上,每次的點選都會建立一個新的線程,這樣任務就可以在多個線程中并發執行。

兩外一個需要注意的地方是,點選按鈕之後更新textview的文字的代碼被去掉了。就像之前提到的,要更新界面上的内容隻能在主線程中進行。要實作這個功能就需要給單獨開辟的線程引入handler執行個體。

實作一個thread handler

線程的handler的實作是放在主線程中的,主要就是用來響應子線程的message并根據這個message來更新主線程的。

handler繼承自android的handler類。用來表明線程的runnable執行個體即将執行,或overridehandlemessage方法,這個方法接受和處理子線程發送的message。本例會用handler來更新使用者界面。

Android線程和線程Handler基礎一覽
Android線程和線程Handler基礎一覽

上面的代碼中聲明了一個handler并實作了handlemessage回調方法。當子線程發出message的時候可以被這個方法處理。在這個執行個體中,隻是簡單地在代碼中設定了textview執行個體的文字。

現在就剩下修改button點選事件中建立的線程了。我們需要在這個線程裡發出一個消息告訴handler20秒的延時任務已經執行完成。

Android線程和線程Handler基礎一覽
Android線程和線程Handler基礎一覽

這段修改中唯一的修改就是增加了的就是handler調用sendemptymessage方法。由于handler執行個體不需要特别發送什麼message是以這裡隻發送空消息。執行代碼之後,點選按鈕,等待20秒。textview就會顯示新的文本。

給handler傳遞消息

之前的代碼調用了handlemessage方法。但是這個方法并沒有發揮出message可以發送資料給handler的優點。下面就會對現有的代碼做出更多的修改來在子線程和handler執行個體之間傳遞資料。首先,在建立的子線程中會從系統擷取到date和time,并轉換成字元串。這些内容會儲存在一個bundle執行個體中。然後調用handler的obtainmessage方法從message池中擷取一個message執行個體。最後,這個儲存了系統資訊的bundle會被添加到message執行個體中并被sendmessage方法發送給handle執行個體。

Android線程和線程Handler基礎一覽
Android線程和線程Handler基礎一覽

接下來更新handlemessage方法。用這個方法把接收到的時間顯示在textview執行個體中。

Android線程和線程Handler基礎一覽
Android線程和線程Handler基礎一覽

最後編譯運作代碼,點選按鈕測試一下我們的修改是否成功。

總結

本教程就是提供一個對于android應用實作多線程的概覽。當一個app運作在一個程序中的時候,系統會給這個app穿件一個主線程。主線程的主要功能就是處理使用者輸入,是以任何執行時間過長的任務都會導緻主線程無法及時響應使用者後續的輸入。是以,耗時的任務都應該放在另外開辟的子線程中執行。這些都是很基礎的。因為android使用者界面的各種元素都是非線程安全的,是以對于界面的修改智能在主線程中進行。在主線程中可以使用handler執行個體來接受子線程發出的消息來更新界面元素。

歡迎加群互相學習,共同進步。qq群:ios: 58099570 | android: 330987132 | go:217696290 | python:336880185 | 做人要厚道,轉載請注明出處!http://www.cnblogs.com/sunshine-anycall/p/4755152.html

繼續閱讀