背景:
我們開發應用程序的時候,處於線程安全的原因子線程通常是不能直接更新主線程(UI線程)中的UI元素的,那么在Android開發中有幾種方法解決這個問題,其中方法之一就是利用Handler處理的。
下面說下有關Handler相關的知識。
多線程一些基礎知識回顧:
在介紹Handler類相關知識之前,我們先看看在Java中是如何創建多線程的
方法有兩種:
通過繼承Thread類,重寫Run方法來實現
通過繼承接口Runnable實現多線程
具體兩者的區別與實現,看看這篇文章中的介紹:http://developer.51cto.com/art/201203/321042.htm
接下來讓我們看看Handler是什么?如何來用
Handler是這么定義的:
主要接受子線程發送的數據, 並用此數據配合主線程更新UI.
Handler的主要作用:主要用於異步消息的處理
Handler的運行過程:
當(子線程)發出一個消息之后,首先進入一個(主線程的)消息隊列,發送消息的函數即刻返回,而在主線程中的Handler逐個的在消息隊列中將消息取出,然后對消息進行處理。這樣就實現了跨線程的UI更新(實際上還是在主線程中完成的)。
這種機制通常用來處理相對耗時比較長的操作,如訪問網絡比較耗時的操作,讀取文大文件,比較耗時的操作處理等。
在大白話一點的介紹它的運行過程:
啟動應用時Android開啟一個主線程 (也就是UI線程) , 如果此時需要一個耗時的操作,例如: 聯網讀取數據,或者讀取本地較大的一個文件的時候,你不能把這些操作放在主線程中,如果你放在主線程中的話,界面會出現假死現象(這也就是你在主線程中直接訪問網絡時會提示你異常的原因,如我們上篇文章所述Android主線程不能訪問網絡異常解決辦法
)。
這個時候我們需要把這些耗時的操作,放在一個子線程中,因為子線程涉及到UI更新,Android主線程是線程不安全的,更新UI只能在主線程中更新.。
這個時候,Handler就出現了,來解決這個復雜的問題,由於Handler運行在主線程中(UI線程中), 它與子線程可以通過Message對象來傳遞數據, 這個時候,Handler就承擔着接受子線程傳過來的(子線程用sedMessage()方法傳弟)Message對象,(里面包含數據) , 把這些消息放入主線程隊列中,配合主線程進行更新UI。
接下來我們看看關於Handler都有哪些方法(它都能干什么):
其中Handler對象的一些主要方法,如下:
post(Runnable) postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
正如方法名字中看到的,有兩類方法:
(1)在某個主線程中執行Runnable
(2)在子線程中發送一個消息,在主線程中檢測該消息處理
線程間傳遞Message對象的sendMessage方法和發送Runnable多線程對象的post方法。正對應着上面所說的兩個特性1)、2)
下面開發個Handler實例做說明:
用post的方法執行一個Runnable對象,在該對象中隨機產生一個10-100之間的隨機數,賦值到UI主線程中的TextView中線程,執行5次,每次相隔5秒, 拼接每次的數字, 最后執行結果應該如:10 22 33 44 61
主要代碼如下:
int i = 0;@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler.post(run);
}Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
String s = String.valueOf(msg.what);
TextView tv = (TextView)findViewById(R.id.textView);
tv.setText(tv.getText() + ” ” + s);
}
};Runnable run = new Runnable(){
@Override
public void run(){
Random r = new Random();
int rnum = r.nextInt((100 – 10) + 1) + 10;
handler.sendEmptyMessage(rnum);
handler.postDelayed(run, 5000);
i++;
if (i==5){
handler.removeCallbacks(run);
}
}
};