線程:後臺異步任務AsyncTask

去五金店買個鑽,不是由於咱們須要鑽,咱們只需須要孔,既然五金店沒法買孔,退而求其次,買打孔的工具。一樣的對於後臺線程,咱們真正須要的是可以在UI主線程外進行處理,Android提供一個讓程序員編寫後臺操做更爲容易和透明AsyncTask。java

使用AsyncTask,須要建立AsyncTask的資料,並實現其中的抽象方法以及重寫某些方法。利用AsyncTask咱們不須要本身來寫後臺線程,無需終結後臺線程,例如stop()的方式。AsyncTask的方式對無限循環的方式並不太合適,可能更合適使用Runnable或者Thread。android

對於初次使用的人,AsyncTask看起來有一些複雜。咱們先學些AsyncTask的基本狀況,而後給出一個小例子來驗證。程序員

AsyncTaskweb

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中加入條目。ide

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和內存,是有代價的,咱們應該確保它處理的時候更爲有效。

相關文章
相關標籤/搜索