關於UI執行緒與非UI執行緒互動,有關Handler機制等(一)
在Android中,一個activity有一個主執行緒也叫UI執行緒,作用就是用來繪製UI介面,在這個執行緒裡面,你的應用和android的UI元件發生互動。所以當你需要進行某些費時操作的時候,比如訪問網路等,如果放入UI執行緒,就會阻塞介面的繪製,當介面不能繪製的時候,整個app看起來就跟卡死一樣,更可怕的是,當UI執行緒掛起時間太長,就會發生ANR。這顯然不是一種好的使用者體驗。另外,UI元件也並不是執行緒安全的,所以也最好不建議從非UI執行緒呼叫UI元件。故我們需要記住以下兩點。
1.不要在UI執行緒裡面寫費時操作,導致UI執行緒阻塞
2.不要在非UI執行緒對繪製介面,可能會導致某些錯誤
非UI執行緒也被稱作為工作執行緒,後臺執行緒,我們可以把各種費時的操作寫在這裡面,比如訪問網路等。但是,當我們處理完費時操作的時候,可能需要重新繪製介面(訪問UI元件),此時我們就需要讓工作執行緒與UI執行緒互動。經過總結,有以下五種方式
1.Handler機制
2.Activity.runOnUIThread(Runnable)
3.View.Post(Runnable)
4.View.PostDelayed(Runnable,long)
5.AsyncTask
Handler機制
Handler的核心就是處理訊息(Message),Handler存在於主執行緒且一直存在,等待著子執行緒(工作執行緒,非UI執行緒)處理完問題後返回Message,然後由Handler接收,在主執行緒處理該Message,並呼叫響應的UI元件,Message就是UI執行緒與非UI執行緒之間的互動資訊。
說道Handler,就不得不提Looper和MessageQueue,這也是Handler裡面不能缺少的兩個部分,Looper英文意思就是環,執行緒通過Looper建立自己的訊息迴圈,MessageQueue是訊息佇列,採用先進先出儲存訊息。Looper負責從MessageQueue中取出訊息,並分發到指定的Handler物件。
Handler實現程式碼
UI執行緒(只能有一個)
private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // TODO 接收訊息並且去更新UI執行緒上的控制元件內容 if (msg.what == 0) { // Bundle b = msg.getData(); // tv.setText(b.getString("num")); tv.setText(String.valueOf(msg.obj)); } super.handleMessage(msg); } };
非UI執行緒
new Thread() {
@Override
public void run() {
// TODO 子執行緒中通過handler傳送訊息給handler接收,由handler去更新TextView的值
try {
for (int i = 0; i < 100; i++) {
Thread.sleep(500);
Message msg = new Message();
msg.what = 0;
msg.obj = "更新後的值:" + i;
handler.sendMessage(msg);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
Activity.runOnUIThread(Runnable)
這個可以直接在子執行緒中寫入對UI元件的操作,XActivity.runOnUIThread就能看出,他可以找到對應XActivity的主執行緒呼叫UI元件
XActivity.currentActivity.runOnUiThread(new Runnable()
{
public void run()
{
Toast.makeText(getApplicationContext(), , "Update My UI",
Toast.LENGTH_LONG).show();
}
});
View.Post(Runnable)
View.PostDelayed(Runnable,long)
待續