1. 程式人生 > >關於UI執行緒與非UI執行緒互動,有關Handler機制等(一)

關於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)

待續