星期五, 9月 09, 2011

worker thread

android應用程式學習筆記

worker thread

最近學到handler,遇到thread的觀念不是很了,就想說先放下handler,回來學習thread。

之前在thread提到,如果只有單一thread的模式,可能因為運行網路存取或資料庫查詢等而阻塞UI thread,使應用程式看起來很不好用。為了避免此問題,應該將需要花較多時間的工作,丟到另一個thread("background" or "worker "thread)執行。

舉個例子,以下的程式碼是一個點擊程式,當點擊後,在另一thread中執行下載圖片的工作,並顯示出來。


public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
            mImageView.setImageBitmap(b);
        }
    }).start();
}

首先,程式碼似乎沒有甚麼問題,因為產生一個新的thread來處理下載文件的工作。然而它違反了第二條單一執行續模式的原則:do not access the Android UI toolkit from outside the UI thread此例子從worker thread修改了ImageView,取代從UI thread修改。如此可能造成無法定義無法預期的行為,到時要追蹤就會變得困難與費時。


如何解決這樣的問題,android提供許多方法可以從其他的thread存取UI thread,以下列表顯示所有方法。

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable , long)
以下我們就用View.post(Runnable)方法來修改上面的程式碼


public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}
現在這樣運行就是thread-safe了:網路下載圖片的工作在另一個htread執行,ImageView在UI thread中操縱。

然而,隨功能增加,程式也越複雜,這樣的程式變得複雜以及困難去維護。為了管理與worker thread越來越多的互動,你也許可以考慮使用Handler,處理來自UI thread的訊息。也許最好的方法是繼承AsyncTask類別,它可以簡化worker thread需要與UI thread的任務。

沒有留言:

張貼留言