Android中AsyncTask應該怎樣使用,會有什麼坑?

![](http://d.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=82bbf5079122720e7b9beafe4efb2670/79f0f736afc379318119d64ce2c4b74543a91165.jpg)

### 1 AsyncTask 回調方法

包括下列四個回調方法,他們會在什麼線程中執行呢?

doInBackground

publicProgress

preExecute

postExectue

通常我們認為:

doInBackground :非同步線程

publicProgress :主線程

preExecute:主線程

postExectue:主線程

但是如果你真這麼認為,你可能需要為此付出代價了,因為由於安卓系統的某些Bug,使得這些方法的執行線程可能未必如此。

### preExecute 和你調用AsyncTask.execute()在同一個線程

如果你在非UI線程裡面調用execute()話,在preExecute中執行UI更新操作,很可能會導致異常:不正確的狀態刷新。

### postExectue, publicProgress使用的是sHandler初始化綁定的線程

通常情況下的安卓系統都會在主線程中載入AsyncTask類,這樣sHandler默認會綁定到主線程上:這是由於無參數Handler構造函數會使用Looper.myLooper()來進行對象創建,所以它取決於調用者的線程。

那麼postExectue和publicProgress默認將在主線程中執行,這並沒有什麼問題。

但是,假設系統有bug,它不在主線程中初始化AsyncTask,那麼postExectue中執行某些UI操作將會導致異常。

(你可以自己實現一個AsyncTask,然後在非UI線程中載入它,然後看看各個方法的執行對應線程)

### doInBackground 的執行線程

這個線程是線程池為你分配的一個線程,也就是說它默認情況下是沒有進行辦法初始化Handler的:因為其不具有Looper.prepare();

這就意味著,在極端情況下,這4個回調方法可能在3個不同的線程中執行,並且還都不是主線程。

### AsyncTask 線程阻塞的問題。

**在doInBackground 執行網路拉取操作是錯誤的寫法!!**

因為在安卓3.0 之後,AsyncTask的默認執行器是順序執行的。

它會一個一個的執行你的任務,而不是並發的執行這些任務。

除了第一次,之後scheduleNext(); 一定在r.run();後執行,

所以即使是並發線程池,也就一個Runnable執行而已。

所以,網路拉取操作可能阻塞其他AsyncTask.不建議在doBackground中執行。

如果你一定要這麼干,請為AsyncTask分配一個額外的執行器。

或者使用v4包裡面的AsyncTask.



推薦閱讀:

TAG:android | Android開發 | Android應用 | Android手機 |