線程-Android

Android中輕鬆使用線程php

翻譯自 http://android-developers.blogspot.jp/2009/05/painless-threading.htmlhtml

  當你第一次啓動一個Android程序的時候,一個被稱爲"mian"的線程就被自動建立了。它被稱爲主線程或者UI線程,它是很是重要的由於負責分發事件給對應的widget(組件),還包含畫圖的事件。主線程貫穿用戶和Android widget的交互的整個過程。例如,你觸摸了屏幕上的按鈕(Button),UI線程派發(dispatch)觸摸(touch)事件給widget,widget設置爲按下狀態並向事件隊列發送一個無效的請求。UI線程把這個請求彈出棧而且通知widget去重畫它本身。java

        單線程模型致使Android程序 低效。由於每次單線程去執行 長時間的操做如網絡請求,數據庫查詢和drawing event(繪圖事件),在這個過程當中會 阻塞程序的界面(UI)。 當長時間的任務正在執行的時候,沒有事件(Event)會被派發(dispatch),包括drawing event(繪圖事件)。從用戶的角度來看,該程序出現了終止。甚至更糟糕的是,若是UI程序被阻塞幾秒後(大約5s)就會出現臭名昭著的ANR 對話框。
        若是想看一下有多糟糕,你能夠寫一個簡單的帶有按鈕的程序,按鈕的點擊事件執行Thread.sleep(2000)代碼。該按鈕將會保持2秒的按下狀態而後恢復正常的狀態。這樣很容易讓用戶感到程序很慢。
        如今你知道了 必定避免在主線程中執行長時間的操做,你可能會 使用額外的線程(後臺線程或者工做線程)去執行長時間操做。讓咱們來看看點擊從網絡下載圖片到ImageView裏的例子:
public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      Bitmap b = loadImageFromNetwork();
      mImageView.setImageBitmap(b);
    }
  }).start();
}
  首先,代碼看上去很好的解決咱們的問題,由於它 不會阻塞UI線程,不幸的是,它 違背了單一線程模型:Android UI工具箱(toolkit)不是一個線程安全的,而且它老是被放在主線程上操做。
這個ImageView被一個工做線程操做,這致使很是難以想象的問題。跟蹤和修復這樣一個bug很難而且也耗時。
 
        Android提供了 幾種從其餘線程訪問主線程的方式。你可能已經使用他們,可是這裏是齊全的列表:
以上任何一個類都能修正咱們的代碼:
public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      final Bitmap b = loadImageFromNetwork();
      mImageView.post(new Runnable() {
        public void run() {
          mImageView.setImageBitmap(b);
        }
      });
    }
  }).start();
}
  不幸的是,這些類和方法致使咱們的代碼變得複雜和可讀性差。 當你實現複雜的操做來頻繁的更新界面,使用這種方式變得更加糟糕。爲了解決這個問題,Android1.5提供了一個公共類叫作 AsyncTask,它簡化了任務線程和主線程之間的通訊。
 
        在Android1.0和1.1也可以使用AsyncTask只不過它的名字爲UserTask。
 
        AsyncTask的目的就是 幫助你管理線程。咱們以前的例子很容易被改寫以下形式:
public void onClick(View v) {
  new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask {
     protected Bitmap doInBackground(String... urls) {
         return loadImageFromNetwork(urls[0]);
     }

     protected void onPostExecute(Bitmap result) {
         mImageView.setImageBitmap(result);
     }
 }
AsyncTask經過它的子類才能使用。要記住, 一個AsyncTask實例必須在主線程建立而且只能被執行一次。徹底理解和使用這個類,你能夠閱讀AsyncTask文檔。這裏快速的說一下AsyncTask是怎麼工做的:
1>能夠經過泛型指定它的類型:參數,進度值,任務的結果值。
2>doInBackGround()方法自動在工做線程中只想可以。
3>onPreExecute(),onPostExecute(),onProgressUpdate()方法都在UI線程中執行。
4>doInBackground()方法返回的值被看成參數傳遞給onPostExecute()方法。
5>你可以在doInBackground()方法裏任什麼時候候調用publishProgress()方法在UI線程中去執行onProgressUpdate()方法。
 
除了官方文檔,你能夠閱讀幾個複雜的例子源代碼如Shelves(ShelvesActivity.java和AddBookActivity.java)和Photostream(LoginActivity.java,PhotostreamActivity.java和ViewPhotoActivity.java)。我強烈建議閱讀Shelves的源代碼,看它在配置改變(configuration changes)的時候是如何保存任務的(persist task),當Activity銷燬的時候是怎樣取消任務的。
 
 
不要管它是否使用AsyncTask,總之要記住 單線程模型的兩個原則(rule): 不要阻塞(block)UI線程;確保Android UI toolkit 只能在UI線程中被訪問(access)。
AsyncTask使得作這些事情變得更簡單。
 
若是你想學習更酷的技術,加入Google I/O( http://www.google.com/intl/zh-CN/events/io/2011/)。Android團隊的成員將在這裏進行一些列深層次技術的會議( http://www.google.com/intl/zh-CN/events/io/2010/sessions.html),而且回答你全部的問題。
相關文章
相關標籤/搜索