Android學習筆記(三二):線程:後台非同步任務AsyncTask

來源:互聯網
上載者:User

去五金店買個鑽,不是因為我們需要鑽,我們只需需要孔,既然五金店無法買孔,退而求其次,買打孔的工具。同樣的對於後台線程,我們真正需要的是能夠在UI主線程外進行處理,Android提供一個讓程式員編寫後台操作更為容易和透明AsyncTask。

使用AsyncTask,需要建立AsyncTask的資料,並實現其中的抽象方法以及重寫某些方法。利用AsyncTask我們不需要自己來寫後台線程,無需終結後台線程,例如stop()的方式。AsyncTask的方式對無限迴圈的方式並不太合適,可能更合適使用Runnable或者Thread。

對於初次使用的人,AsyncTask看起來有一些複雜。我們先學些AsyncTask的基本情況,然後給出一個小例子來驗證。

AsyncTask

AsyncTask中有三個參數(例如class MyTask extends AsyncTask<參數1,參數2,參數3>{})

  • 參數1:向背景工作的執行方法傳遞參數的類型
  • 參數2:在背景工作執行過程中,要求主UI線程處理中間狀態,通常是一些UI處理中傳遞的參數類型
  • 參數3:背景工作執行完返回時的參數類型

其中參數1和參數2是一個varags,例如String…,相當於String[]。

對於AsyncTask的使用步驟如下:

  • 建立一個AsyncTask的子類,對象建立時帶參數(參數1,參數2,參數3)
  • 調用對象的excute()時,將啟動後台進程,執行doInBackground()的代碼。excute()中所傳遞的參數類型在參數1中描述,屬於範式定義
  • 如果我們希望在啟動後台進程中,進行某些初始化的處理,可以override onPreExecute()方法,注意這些代碼是在UI線程中執行的
  • 在執行完後台進程,我們需要進行某些處理,例如停止某些UI的動態畫面,進度條消失等等,可以重寫onPostExecute()方法,同樣,這些代碼也是在UI主線程中執行。其中將doInBackground()的傳回值傳遞作為onPostExecute()參數中,其類型由參數3描述
  • 在執行後台進程中,如果需要需要向UI線程報告某個處理狀態,可以通過publishProgress()來觸發,這樣在UI主線程中將執行重寫後的onProgressUpdate()的代碼,其中傳遞的參數的類型由參數2描述。

一個小例子

有一個ListView的小例子,一開始List中沒有內容,通過一個AsyncTask逐步在List中加入條目。

1)XML檔案:簡單的ListView布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ... ...>
  <ListView android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" /> 
</LinearLayout>

2)例子代碼

public class Chapter15Test3 extends ListActivity{
    //這裡是List Item內容,在這個例子中,將在背景工作中逐個加入
    private static String[] items={"lorem", "ipsum", "dolor","sit", "amet", "consectetuer","adipiscing", "elit", "morbi","vel", "ligula", "vitae","arcu", "aliquet", "mollis","etiam", "vel", "erat","placerat", "ante","porttitor",
"sodales","pellentesque", "augue","purus"};

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chapter_8_test2);
        //在這個例子中,我們一開始並沒有匯入items的資料,注意item資料為建立的ArrayList,即無內容
        setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,new ArrayList<String>()));
        //步驟5:建立背景工作的對象,並通過execute()啟動後台線程,調用doInBackground()的代碼,execute中的參數類型為參數1,這裡我們不需要傳遞任何內容
        new AddStringTask().execute();
    }
  
    //步驟1:建立AsyncTask子類,參數1是Void的範式類型,參數2是String的範式類型,參數3是Void 。其中參數1:向背景工作的執行方法傳遞參數的類型;參數2:在背景工作執行過程中,要求主UI線程處理中間狀態,通常是一些UI處理中傳遞的參數類型;參數3:背景工作執行完返回時的參數類型。
    private class AddStringTask extends AsyncTask<Void, String,Void>{
       //我們加入一個檢測資訊的方法,列印當前在哪個線程執行的資訊
        private void printInfo(String info){
            Log.d("WEI", info + " : Tread is " + Thread.currentThread().getName());
        }
  
        //步驟2:實現抽象方法doInBackground(),代碼將在後台線程中執行,由execute()觸發,由於這個例子並不需要傳遞參數,使用Void...,具體書寫方式為範式書寫
        protected Void/*參數3*/ doInBackground(Void...params/*參數1*/) {
            for(String item : items){
                //步驟3:通知UI主線程執行相關的操作(在onProgressUpdate中定義)
                publishProgress(item/*參數2*/);
                printInfo("doInBackgound " + item);
                SystemClock.sleep(200);
            }
            return null;
        }

        //步驟3:定義收到pushProgress()觸發後,在UI主線程執行的內容,在本例,將item加入list中。方法中的參數為範式方式,實質為數組,由於我們只傳遞了item一個String,要擷取,為values[0]
        protected void onProgressUpdate(String...
values/*參數2*/) {
            printInfo("onProgressUpdate  get param " + values[0]);
            ((ArrayAdapter<String>)getListAdapter()).add(values[0]);
        }
      
        //步驟4:定義後台進程執行完後的處理,本例,採用Toast
        protected void onPostExecute(Void result/*參數3*/) {
            printInfo("onPostExecute");
            Toast.makeText(Chapter15Test3.this, "Done!", Toast.LENGTH_SHORT).show();
        }         
    }   
}

我們根據printInfo跟蹤各部分代碼在哪裡執行:doInBackground在後台線程執行,onProgressUpdate()和onPostExecute()在UI主線程執行。main就是UI主線程,而AsyncTask #1為後台線程,名字不一樣。

 

需要注意

雖然Android提供背景工作方便我們處理,是否使用背景工作,以及如何使用背景工作,我們要注意下面的內容:

可能在執行後台線程處理中,使用者和UI之間存在互動,這些交換可能會對背景工作有重要的影響,因此需要通知後台線程,Android提供很多的類來處理,封裝在java.util.concurrent包中,協助與後台線程的安全通訊。可能在執行後台線程處理中,我們的Activity就已經被kill了,例如有一個電話過來,然後發給簡訊,查看號碼本。這時系統可能將你的activity踢走,接著後面我們會學習Activity的生命週期,瞭解相關的情況。在編程中,出現這種情況,只要有可能,需要將後台進程關閉。可能在執行後台線程處理中,出現某種錯誤,例如後台在下載URL,而網路連接中斷了。這種情況下關閉後台進程可能是最好的處理。此外背景工作是消耗CPU和記憶體,是有代價的,我們應該確保它處理的時候更為有效。

相關連結:我的Andriod開發相關文章

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.