AsyncTask類原型
public abstract class AsyncTask<Params, Progress, Result>
- Params:傳遞給AsyncTask的類型阅仔,作為doInBackground的參數(shù)類型
- Progress:作為onProgressUpdate和publishProgress的參數(shù)類型
- Result:由doInBackground返回谍椅,作為onPostExecute的參數(shù)類型
使用規(guī)則
- 該類實例必須在UI線程中創(chuàng)建
- execute方法必須在UI線程中調用
- 一個任務實例只能執(zhí)行一次
執(zhí)行流程
- onPreExecute:在UI線程中執(zhí)行,一般用于任務執(zhí)行前初始化UI铆农,如顯示進度條對話框等
- doInBackground:在后臺執(zhí)行,期間可以調用publishProgress來更新進度條等內(nèi)容
- onProgressUpdate:當publishProgress調用時在UI線程中執(zhí)行,可更新進度條或顯示文本等信息
- onPostExecute:在UI線程中執(zhí)行墩剖,可以利用返回的結果更新UI猴凹,或者關閉進度條對話框等。
- onCanceled: 該方法運行在UI線程中岭皂,可以在方法中關閉進度條對話框等郊霎。
任務的取消
可以調用cancel取消任務,之后isCancelled會返回true爷绘。
取消任務后书劝,doInBackground返回后,onPostExecute不再執(zhí)行土至,而是onCancelled執(zhí)行购对。
為了盡快取消任務,應該在doInBackground中調用isCancelled檢查任務是否取消陶因,以采取相應的行動骡苞。
在編寫doInBackground方法時,應該不時地檢查isCanceled的返回值楷扬,如果返回true解幽,應該停止執(zhí)行任務。
在onPostExecute中烘苹,應該調用isCanceled檢測任務是否已經(jīng)被取消躲株。
另外,在調用execute執(zhí)行后螟加,應該注意它的取消操作徘溢。
例如在Activiy中,應該在Activity不可見時(onStop方法)取消操作捆探。
當配置變化時
當配置變化時然爆,如果進行了合適的取消,當Activity或Fragment重新啟動時黍图,會導致任務重新開始曾雕。
為了避免在配置變化時重新開始,可以把AsyncTask保存在Fragment中助被,當配置變化時剖张,使用Fragment保證任務不會中斷。
如果在執(zhí)行任務時揩环,同時顯示了加載對話框搔弄,可以在配置變化時,dismiss對話框丰滑,當重新開始時顾犹,再顯示對話框。
http://blog.csdn.net/lmj623565791/article/details/37936275
AsyncTask的適用場景和內(nèi)存泄漏
AsyncTask應該用于短時間的任務。
如果作用于長時間的任務炫刷,且是內(nèi)部類擎宝,那么保存了Activity的引用,會導致Activity不會被垃圾回收浑玛∩苌辏可以通過靜態(tài)類來解決。
同時顾彰,在更新UI時极阅,會拋出異常【醒耄可以通過實現(xiàn)合適的取消機制來解決涂屁。
實現(xiàn)原理
為了實現(xiàn)可取消的操作书在,內(nèi)部使用了FutureTask類灰伟。
同時,內(nèi)部使用了線程池儒旬,默認情況下栏账,只有一個任務在執(zhí)行,其他任務會入隊列等待執(zhí)行栈源〉簿簦可以通過構造方法,傳遞自定義的Executor來并行執(zhí)行甚垦。
-在Android 3.0之前茶鹃,線程池可以并行執(zhí)行5個任務,最大為128.
在Android 3.0及其之后艰亮,默認線程池為串行執(zhí)行闭翩。
最后,為了能夠更新UI迄埃,使用可擴展了Handler的靜態(tài)內(nèi)部類疗韵,它的Looper使用的是UI線程的。所以侄非,可以發(fā)送消息給該Handler以更新進度條和UI等蕉汪。
另外,根據(jù)源碼可知逞怨,調用execute后者疤,onPreExecute在調用線程中執(zhí)行,所以AsyncTask必須在UI線程中執(zhí)行叠赦。
因為AsyncTask中有些方法是根據(jù)調用線程來作為參數(shù)驹马,所以AysncTask應該在UI線程中創(chuàng)建。
至于一個AsyncTask只能執(zhí)行一次,我想可能是因為如果允許執(zhí)行多次的話窥翩,如果線程池為多個線程并行執(zhí)行业岁,那么我們在擴展該類時,必須考慮線程同步的問題寇蚊,這樣就有點麻煩了笔时。
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
...
onPreExecute();
exec.execute(mFuture);
return this;
}