2014-10-06 171 views
1

在我的應用程序中,我有一個AsyncTask,並且我還創建了一個列表,將任務添加到該列表中。 在AsyncTask中,我下載了一些信息,它工作得很好,但是當使用finish()關閉活動時,我經常得到強制關閉,因爲AsyncTask沒有關閉,並且它到達onPostExecute並且想要與UI交互它崩潰導致活動被破壞!如何在Android中強制停止AsyncTask

這是我做過嘗試,但沒有奏效:

for (int i = 0; i<tasks.size(); i++){ 
      tasks.get(i).cancel(true); 
     } 
    finish(); 

那麼有沒有辦法強制停止AsyncTasks?

+2

使用'myAsynTask.cancel(真);' – KOTIOS 2014-10-06 12:35:00

+1

他已經這樣做了。這個問題不是重複的。 – konmik 2014-10-07 07:41:05

回答

1

你需要告訴你的AsyncTask它應該取消它的工作。因此,您需要定期檢查您的AsyncTask實施中的self.isCanceled()。如果結果是true您的實施需要停止工作,否則它將完成整個工作或永遠運行,具體取決於實施情況。

2

嘗試創建自己的布爾變量。

boolean stopNow = false; 
asyncTask.start(); 

...裏面異步:

while(...) 
{ 
    if(stopNow == true) finish(); // return(); 
    ... your main async code 
} 

....外異步(在那一刻,當你需要強制停止異步,你的情況在Activity.onDestroy()或Activity.onPause( )):

stopNow = true; 
1

您應該檢查AsyncTask的onPostExecute中是否有活動isDestroyed()。 此外,如果您使用內部AsyncTask類,然後使其靜態。 使用WeakReference引用yout Activity來防止內存泄漏。 (沒有辦法強制停止AsyncTask)。

+0

'onCancelled()'方法[在取消任務部分的官方文檔中聲明](http://developer.android.com/reference/android/os/AsyncTask.html#cancel(布爾值)) – kId 2014-10-06 12:58:52

+0

此方法的作用不會中斷你的任務。它被稱爲在你的任務完成後。 – konmik 2014-10-07 07:37:21

3

您intereset在asyncTask.cancel(true),在其實際參數傳遞true,如文檔住宿:

mayInterruptIfRunning真,如果執行此任務的線程應該被中斷;否則,正在進行的任務被允許完成。

那麼你AsyncTask.doInBackground裏面你可以try/catch語句如下 - 但是這需要你有阻斷拋出InterruptedException電話,否則,你需要經常檢查isCancelled()時間:

@Override 
protected Void doInBackground(Void... params) { 
    try { 
    /// do work, 
    } catch (InterruptedException e) { 
    if (isCancelled()) { 
     // cancel(true) called, dont touch UI! 
    } 
    } 
    return null; 
} 

此外,它的安全檢查是在onPostExecute()開始isCancelled()。

當它達到onPostExecute並希望與UI交互

,它崩潰

這就是另外一個問題,如果你的內心AsyncTask與GUI交互,我建議首先:使你的AsyncTask一個靜態類,將對Activity或Fragment的引用傳遞給AsyncTask構造函數,然後將其存儲爲WeakReference<MyActivity> actRef。那麼當你需要它時使用if(actRef.get()!= null){//使用它。 }。通過這種方式,您需要泄漏對您的活動/片段的引用或使用無效的UI對象。

1

這裏的例子,如何實現這一目標?

public class MyTask extends AsyncTask<Void, Void, Void> { 

private volatile boolean running = true; 
private final ProgressDialog progressDialog; 

public MyTask(Context ctx) { 
    progressDialog = gimmeOne(ctx); 

    progressDialog.setCancelable(true); 
    progressDialog.setOnCancelListener(new OnCancelListener() { 
     @Override 
     public void onCancel(DialogInterface dialog) { 
      // actually could set running = false; right here, but I'll 
      // stick to contract. 
      cancel(true); 
     } 
    }); 

} 

@Override 
protected void onPreExecute() { 
    progressDialog.show(); 
} 

@Override 
protected void onCancelled() { 
    running = false; 
} 

@Override 
protected Void doInBackground(Void... params) { 

    while (running) { 
     // does the hard work 
    } 
    return null; 
} 

// ... 

} 
相關問題