實際項目中有這么一個問題,用戶進入詳情界面,那么我們就要網絡加載數據並展現在UI上,這個加載用線程或者異步。
這里就拿項目中統一用異步任務來獲取網絡數據把。
用戶可能會有這么一個操作,它在一個商品(說說等)列表中,點擊一個列表項,進入到相應的詳情界面,這時候,我們會開啟一個異步任務來獲取網絡數據,但是網絡差的情況下, 用戶可能就不願意等了,立馬按后退按鈕回到列表,點擊下一個別的列表項進入詳情界面,發現加載太慢,又按后退鍵,如此反復,那么就導致此時有多個異步任務在執行,或者出現OOM問題,或者出現異步任務等待問題。
那么,作為開發者,我們對應的解決方案,便是在用戶在詳情界面按退出按鈕退回到上一個界面的時候,把沒有執行完的異步任務給結束掉。
------------------------------------------------------------------------------------------------------------------------------
現在我們發現了這個問題,又有了解決方案。那么就用代碼來實現了。
那么 取消異步任務怎么做?
我一開始這樣做,AsyncTask.cancel(true);
看下參數的定義:
@param mayInterruptIfRunning <tt>true</tt> if the thread executing this * task should be interrupted; otherwise, in-progress tasks are allowed * to complete.
1、如果是true,如果線程執行,則會被打斷
2、如果是false,線程將會被運行執行完成
看到這,很顯然,我們以為.cancel(true)就會結束掉我們開啟的正在執行的異步任務
但是實際上並沒有結束掉我們想要結束的異步任務~~
看了些別人對此的解釋:
AsyncTask不會不考慮結果而直接結束一個線程。調用cancel()其實是給AsyncTask設置一個"canceled"狀態。這取決於你去檢查AsyncTask是否已經取消,之后決定是否終止你的操作。對於mayInterruptIfRunning——它所作的只是向運行中的線程發出interrupt()調用。在這種情況下,你的線程是不可中斷的,也就不會終止該線程。
那么該如何結束線程呢?
可見.cancel()是給AsyncTask設置一個"canceled"的狀態,那么想要終止異步任務,就需要在異步任務當中結束。
@Override public void onProgressUpdate(Integer... value) { // 判斷是否被取消 if(isCancelled()) return; ......... } @Override protected Integer doInBackground(Void... mgs) { // Task被取消了,馬上退出 if(isCancelled()) return null; ....... // Task被取消了,馬上退出 if(isCancelled()) return null; } ...
另外結束異步任務的條件:
if(loadAsyncVedio!=null && !loadAsyncVedio.isCancelled() && loadAsyncVedio.getStatus() == AsyncTask.Status.RUNNING){ loadAsyncVedio.cancel(true); loadAsyncVedio = null; }
loadAsyncVedio(異步任務)
如此,便可以有效及時的結束異步任務