2013-05-27 61 views
23

我試圖弄清楚爲什麼Android的AsyncTask通過execute給出參數以及爲什麼傳遞給構造函數似乎沒有完成(至少在文檔中)。我應該給構造函數還是參數AsyncTask.execute(params)?

這是在我看來,最有意義的方式(當然,我的工作實際任務不僅僅是一個和運算更多):

public class FooTask extends AsyncTask<Void, Integer, Long> { 
    private ProgressBar progressBar; 
    private int[] data; 

    public FooTask(ProgressBar progressBar, int... data) { 
     this.progressBar = progressBar; 
     this.data = data; 
    } 

    protected void onPreExecute() { 
     progressBar.setMax(data.length); 
     progressBar.setProgress(0); 
    } 

    protected Long doInBackground(Void... _) { 
     long sum = 0; 
     for (int i = 0; i < data.length; i++) { 
      sum += data[i]; 
      publishProgress(i); 
     } 
     return sum; 
    } 

    protected void onProgressUpdate(Integer... progress) { 
     progressBar.setProgress(progress[0]); 
    } 

    protected void onPostExecute(Long result) { 
     Log.i(TAG, "Sum: " + result); 
    } 
} 

這將因而被使用:

new FooTask(progressBar, 1, 2, 3).execute(); 

但是,這不是文檔談論做這件事的方式;它使用參數​​,像這樣(注意不要使用構造所有,但仍然使用一個字段,因爲否則它會是太可怕了極端):

public class FooTask extends AsyncTask<Object, Integer, Long> { 
    private ProgressBar progressBar; 
    private boolean isMaxSettingUpdate = true; 

    protected Long doInBackground(Object... params) { 
     progressBar = params[0]; 
     long sum = 0; 
     for (int i = 1; i < data.length; i++) { 
      sum += (int) data[i]; 
      publishProgress(i - 1, data.length); 
     } 
     return sum; 
    } 

    protected void onProgressUpdate(Integer... progress) { 
     progressBar.setMax(progress[1]); 
     progressBar.setProgress(progress[0]); 
    } 

    protected void onPostExecute(Long result) { 
     Log.i(TAG, "Sum: " + result); 
    } 
} 

這項任務的執行會看起來更像這樣:

new FooTask().execute(progressBar, 1, 2, 3); 

一個我認爲是給進度條的構造函數和數據到執行呼叫,但我仍然無法使用onPreExecute,因爲我不知道最大值其他選項。 (我寧願使用真正的最大值,而不是任意設置最大值並計算百分比......只是看起來更好。)

餘額在哪裏?我該怎麼辦?使用構造函數有什麼錯誤

回答

11

至於文檔爲什麼做這個方法中的所有內容都可以作爲他們的示例選擇的結果。通常,你更可能擴展你的AsyncTask,而只使用doInBackground(),而不是構造函數。

不管怎麼說,在documentation states

內存可觀測


的AsyncTask保證所有的回調調用在這種 同步的方式,下面的操作是沒有明確的 同步安全。

•在構造函數或onPreExecute()中設置成員字段,並在> doInBackground(Params ...)中引用它們。

•在doInBackground(Params ...)中設置成員字段,並在 onProgressUpdate(Progress ...)和onPostExecute(Result)中引用它們。

這意味着你應該對兩種方法都很好。

作爲一個方面說明,我使用了帶有參數構造函數的AsyncTask,沒有問題,所以我可以備份文檔的狀態。

此外,對於您的具體情況,除非ProgressBar事先設置了不同的最大值,否則應該默認爲100。這意味着你可以讓你的構造函數只接受ProgressBar並且在數據中接受doInBackground()(它也應該是一個成員變量)。然後更新進度的時候,做

(progress[0]/data.length) * 100 

這不會是完美的,你可以轉換到一倍,如果你想提高準確性,但這應該讓最簡單的代碼來理解。

+0

你會如何去進度條的事情嗎?這樣傳遞是否合適? –

+0

既然你確實需要'onPreExecute()',我會用你的第一個,只有構造函數的方法,它滿足要求,它更容易閱讀。儘管如此,你將不得不注意方位的變化。由於活動/片段確實被重新創建,如果發生這種情況,您的任務將保留進度條的舊引用,所以欄不應該爲用戶更新。 –

+0

哦!顯示了我對Android的內部工作原理的瞭解。我從來沒有想過除了他們在前後會是同一個對象之外。因此,我看到通過進度條*不安全。感謝您的清除! –

2

在我看來,如果我想傳遞一些值來初始化UI,就像您提到的ProgressBar一樣,我需要在OnPreExecute()中執行它。而且由於OnPreExecute()不接受任何參數,我寧願將構造函數中的值作爲參數。如果某些值與UI不相關,只需在doInBackground,例如文件的下載URL中,我將它們作爲執行參數傳遞。

所以,如果這些值是關於UI的,那麼在構造函數 中傳遞它們(如果值只是在doInBackground中使用),請將它們作爲execute參數傳遞。

0

如果您想要在主線程上工作(需要參數),您必須將這些參數傳遞給構造函數。

您通過.execute()傳遞的所有內容都將在異步線程上運行。

正如buptcoder提到,主要是將關注UI的東西,但還盤/數據庫操作可以是線程關鍵

相關問題