Android -- 關閉AsyncTask(異步任務)


  前面說了如何操作AsyncTask,這篇我們來說一下如何關閉AsyncTask。

  有人就問了:為什么要關閉AsyncTask呢?很簡單,AsyncTask 是在后台執行耗時操作(獲取數據),當你離開當前頁面或者結束進程時,也就是跳到你另一個頁面不需要當前頁面的數據。如果不關閉,其它頁面無法顯示數據,因為后台還在獲取當前頁面的數據,也可理解為堵塞。

  現在我們再運行一下上一篇博客里的app:

 

我們點擊Back后再次進入App,點擊產看數據

  我們會發現,再次點擊時,數據沒有立刻加載,而是過了一會才加載。有人會講是網絡問題,但我們是模擬的數據加載,沒有經過網絡。

  這就是上面所講的堵塞。AsyncTask在執行多個線程時,是單個執行,其它線程是在緩沖區。當執行一個下一個才開始(One by one)

  那么怎么關閉呢?

  通過api,我們會發現一個 AsyncTask.cancel(true); 

  A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)

  意思是: 

  • 我們可以隨時調用 cancel(boolean)去取消這個加載任務,調用這個方法會間接調用 iscancelled 並且返回true 。
  • 調用cancel()后,在doInBackground()return后 我們將會調用onCancelled(Object) 不在調用onPostExecute(Object)
  • 為了保證任務更快取消掉,你應該在doInBackground()周期性的檢查iscancelled 去進行判斷。

  現在我們就在MainActivity中的onPause(退出時)寫入代碼

 @Override
    protected void onPause() {
        //如果異步任務不為空 並且狀態是 運行時  ,就把他取消這個加載任務
        if(task !=null && task.getStatus() == AsyncTask.Status.RUNNING){
            task.cancel(true);

        }
        super.onPause();
    }

再在AsyncTask 中加上 紅色 代碼,判斷

public class MyTask extends AsyncTask{
    private List<User> userlist;
    private BaseAdapter adapter;
    private MainActivity activity;
    private String barNum;
    public MyTask(MainActivity activity) {
        this.activity = activity;        
    }
    
    @Override
    protected Object doInBackground(Object... params) {
        userlist = (List<User>) params[0];
        adapter = (BaseAdapter) params[1];
        for(int i=1 ;i<=100;i++){
            if(isCancelled()){ break; } try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            userlist.add(new User("zhangsan"+i,18+i,"aa"+i+"aa"));
            publishProgress(i);
            barNum = i+"%";
        }        
        return userlist;
    }
    @Override
    protected void onProgressUpdate(Object... values) {
        if(isCancelled()){ return; }
        Button btn = (Button) activity.findViewById(R.id.button1);
        btn.setVisibility(View.GONE);
        TextView num = (TextView) activity.findViewById(R.id.barNum);
        int bar = Integer.parseInt(values[0].toString());
        /*bar = (bar)*25;*/
        ProgressBar progressBar = (ProgressBar) activity.findViewById(R.id.seekBar1);
        progressBar.setProgress(bar);
        num.setText(barNum);
        //progressBar.setBackgroundColor(activity.getResources().getColor(R.color.orange));
        /*progressBar.setBackgroundResource(R.color.orange);*/
        adapter.notifyDataSetChanged();
    }
    
}

  這時,當我Back后再點進來加載,立馬就開始了。有人會覺得疑惑:我在退出前不是cancel 了嗎?為什么還要在異步任務中進行分步判斷。

  當在onPause中 cancel 掉,取消了這個異步加載,但是在AsyncTask 中的isCanceled 值是一直沒變,默認false , 即不關閉。

  

謝謝大家的關注。 I am big!It's the picture that got small.    ---- 我是巨大的!是那些照片讓我變得渺小了。(《日落大道》)   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM