在一個Activity頁面,如果發起了AsyncTask任務,然后頁面離開/銷毀了,此時如果doInBackground沒執行完,會有兩個問題:
1, AsyncTask白白消耗資源,結果已經用不上了,因為UI也不在;
2, AsyncTask如果聲明為Activity的內部類,會持有Activity這個宿主類,導致Activity內存泄露。
所以一定要在Activity onDestory的時候cancel掉AsyncTask任務。
怎么從一個App的架構層面來約束所有的業務模塊都自動做這個事情呢?
1, 自定義一個AutoCancelAsyncTask,繼承AsyncTask,定義一個成員變量,叫id。
2, 定義一個TaskManager單例類,維護一個AutoCancelAsyncTask隊列。
3, 在AutoCancelAsyncTask的構造方法中,把自己加到TaskManager的隊列。
4, 在AutoCancelAsyncTask中重寫onCancelled和onPostExcute方法,調用TaskManager的一個方法,這個方法從隊列中刪除id對應的AutoCancelAsyncTask。
5, 定義BaseActivity,這個類生成一個唯一標識自己的id。
6, 業務Activity都繼承BaseActivity,發起的AsyncTask都繼承AutoCancelAsyncTask,並傳入activity的唯一id給AutoCancelAsyncTask的id。
7, 在BaseActivity的onDestory方法中調用TaskManager的一個方法,這個方法接收當前activity的id,然后遍歷隊列,找到與傳入的id相同的AutoCancelAsyncTask,然后調用其cancel方法。
PS:
1, 如果害怕業務子類重寫AutoCancelAsyncTask的onCancelled或者onPostExcute的時候不調用super導致沒從隊列中刪除這個Task,可以final這兩個方法,給子類另外留兩個接口出來;
2, 假如doInBackground中是個慢操作任務,調用cancel基本都能取消掉提現結束;但如果是個循環,沒用! 所以好的做法是在循環的條件判斷中假如this.isCancelled()判斷,如果是true,直接break循環。