天天看點

Android AsyncTask 使用時需要注意的地方

使用 AsyncTask 可以友善的實作分線程執行耗時任務,完成後更新 UI 這個需求,但是由于 AsyncTask 的自身特點,有以下幾個地方需要注意:

  • 相容老版本時 AsyncTask 執行順序的問題
  • 記憶體洩露風險
  • 與 Activity 生命周期不相同

執行順序問題

在 Android 1.6 到 2.3.2 中,AsyncTask的執行順序修改為并行執行。如果同時執行多個任務,則這些任務會并行執行。 當任務通路同一個資源的時候 會出現并發問題。

而在 Android 3.0 以後的版本中,AsyncTask 又修改為了順序執行,并且新添加了一個函數 executeOnExecutor(Executor),如果您需要并行執行,則隻需要調用該函數,并把參數設定為并行執行即可。

參數如下:

* Executors.newCachedThreadPool()。即建立一個單獨的線程池。

* AsyncTask.THREAD_POOL_EXECUTOR。使用現有的線程池,并發執行

* AsyncTask.SERIAL_EXECUTOR。效果和 execute() 一樣。

記憶體洩露風險

在 Activity 中,将 AsyncTask 作為内部類時, 這個類會隐式的引用這個 Activity 。當這個 task 的 run 沒有執行完時,這個 Activity 就不會被銷毀。

與 Activity 生命周期不相同

當 Activity 結束的時候,如果 AsyncTask 沒有執行完成,它會以它自有的方式繼續運作,即使你退出了整個應用程式。AsyncTask提前結束的唯一方法是通過調用AsyncTask.cancel()進行取消。

這表明你必須親自管理 AsyncTask的取消操作;否則,由于不必要的背景線程會導緻app阻塞的風險,或者記憶體洩露。當不再需要一個AsyncTask時,一定要取消它,防止在app執行期間引起任何問題。

AsyncTask 和 Activity 容易引起的另外一個問題是螢幕旋轉時引起的異常。如果你在一個 Activity 中建立了一個 AsyncTask,你旋轉了螢幕,這個 Activity 将會被銷毀并且會重新建立一個新的執行個體。但是 AsyncTask 沒有銷毀,它将會繼續執行直到完成。當它執行完成後,它實際上是更新了上一個已經不存在的 Activity,如果你原本想在 onPostExecute() 中更新 UI 的話,這時的 AsyncTask 将不會更新新的 Activity,并且這個操作會引發一個異常:java.lang.IllegalArgumentException。

如果你是想要在 onPostExecute() 中關閉一個 dialog,則會發生:java.lang.IllegalArgumentException: View not attached to window manager(前提是你忘記在Activity的onStop()中忘記dismiss)。不僅如此,還會在show()的調用出抛出一個 lead window的異常

AsyncTask 隐藏的陷阱

Android App 記憶體洩露之Thread