2011-07-29 77 views
43

當活動第一次啓動時,我有我的asyncTask運行,然後如果網絡連接不可用,那麼我有一個刷新按鈕,嘗試運行asyncTask再試一次。但我得到一個調試錯誤說這個..如何多次運行同一個asynctask?

07-29 18:14:21.290: ERROR/AndroidRuntime(9080): FATAL EXCEPTION: main 
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once) 
    07-29 18:14:21.290: ERROR/AndroidRuntime(9080):  at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:541) 
    07-29 18:14:21.290: ERROR/AndroidRuntime(9080):  at android.os.AsyncTask.execute(AsyncTask.java:499) 
    07-29 18:14:21.290: ERROR/AndroidRuntime(9080):  at com.fttech.gameIT.MainMenu$1.onClick(MainMenu.java:90) 

有沒有反正跑這兩次?

回答

66

只需創建另一個實例並執行它。

+0

,但我知道的東西是什麼如果用戶多次點擊該按鈕......則只執行一次,然後在第二次點擊後強制關閉 –

+4

禁用該按鈕,直到「AsyncTask」返回?順便說一句,這是正確的方法,需要產生一個新的'AsyncTask'。 – dmon

+0

使它成爲一個單身人士 if(task!= null then) make並運行任務 – Pyrodante

16

你永遠無法在Java再次執行一個線程,不,不以任何其他語言,一旦線程與run()方法做,你不能重新啓動它,這就是爲什麼你所得到的IllegalStateException

但是,您可以仍然調用該線程的方法,但他們將被要求他們在不同的線程線程上運行。因此您將不得不創建一個新的。

+0

嗯....那麼wouldnt工作..因爲onClick ..讓我們說,如果用戶不斷點擊它..它會運行一次,並給一個強制關閉錯誤..無論如何有一個按鈕,使一個應用程序關閉然後打開備份?或重新加載活動? –

+0

@ Coder_For_Life22處理雙擊的方式是,忽略對該按鈕的任何其他點擊並在點擊一次後更改其外觀。 –

+0

我不明白你的意思? –

4

只需進行新的調用,如新的asyncTask()。execute();您必須創建一個新對象才能重新啓動該任務。

+0

@ Darrell:除非你更詳細地描述你做了什麼以及出了什麼問題,否則沒用。 – ToolmakerSteve

2

我只是創建了asynctask,然後創建了一個可創建asynctask的新實例的runnable。然後你可以一次又一次地將你的runnable提交給處理程序。

class MyAsyncTask extends AsyncTask<String, Void, String>{ ...} 

Runnable myRunner = new Runnable(){ 
    public void run() { 
     new MyAsyncTask().execute(...); 
}}; 
myHandler.post(myRunner); 
+2

仍在創建異步任務的新對象。更好地使用它,無需運行 – rDroid

27

就像線程一樣,AsyncTask s不能被重用。每次你想運行一個新的實例時,你都必須創建一個新的實例。

0

我創建了一個類型爲ProgressUpdater(擴展AsyncTask的類的名稱)的Arraylist並將它添加到它(在按鈕的onClick中)。所以你可以在需要時執行和取消這些任務。

public class MainActivity extends Activity { 
ProgressBar progress; 
ProgressUpdater task; 
ArrayList<ProgressUpdater> pu = new ArrayList<MainActivity.ProgressUpdater>(); 
int count = 0; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    progress = (ProgressBar) findViewById(R.id.progress); 

} 

public void onClick(View v) { 
    switch (v.getId()) { 
    case R.id.btn: 
     task = new ProgressUpdater(); 
     pu.add(task); 
     count++; 
     pu.get(count - 1).execute(0); 
     System.out.println("task" + task); 

     // task.execute(10); 
     break; 
    case R.id.btnCancel: 
     if (count >= 0) { 
      pu.get(count - 1).cancel(true); 
      pu.remove(count - 1); 
      count--; 
     } 
     // task.cancel(true); 

     break; 

    } 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 

private class ProgressUpdater extends AsyncTask<Integer, Integer, Void> { 
    @Override 
    protected void onPreExecute() { 
     // TODO Auto-generated method stub 
     super.onPreExecute(); 
     progress = (ProgressBar) findViewById(R.id.progress); 
     progress.setMax(100); 
    } 

    @Override 
    protected Void doInBackground(Integer... params) { 
     // TODO Auto-generated method stub 
     int start = params[0]; 
     for (int i = start; i <= 100; i++) { 
      try { 
       boolean cancelled = isCancelled(); 
       if (!cancelled) { 
        publishProgress(i); 
        SystemClock.sleep(100); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     // TODO Auto-generated method stub 
     super.onPostExecute(result); 
     Log.v("Progress", "Finished"); 
    } 

    @Override 
    protected void onCancelled() { 
     // TODO Auto-generated method stub 
     super.onCancelled(); 
     progress.setMax(0); 

    } 

    @Override 
    protected void onProgressUpdate(Integer... values) { 
     // TODO Auto-generated method stub 
     super.onProgressUpdate(values); 
     progress.setProgress(values[0]); 
    } 

} 

}

2

不能運行的AsyncTask的相同實例不止一次。 讓我們假設你有一個名爲的AsyncTask和MyAsyncTaks你打算做這樣的事情,

MyAsyncTask myAsyncTask = new MyAsyncTaks(); 
    myAsyncTask.execute(); // Works as expected 
    . 
    . 
    . 
    . 
    myAsyncTask.execute(); // This will throw you exception 

這樣做的原因是,一個線程一旦完成其「跑」的方法,不能分配其他任務。這裏,在第一次調用execute()時,你的AsyncTask開始運行並且在完成其工作之後開始運行,該線程就不能運行。當然,下一次調用execute()會引發你異常。

不止一次運行此程序的最簡單方法是創建MyAsyncTaks的新實例並對其執行調用。

MyAsyncTask myAsyncTask = new MyAsyncTaks(); 
    myAsyncTask.execute(); // Works as expected 
    . 
    . 
    . 
    MyAsyncTask myAsyncTask2 = new MyAsyncTaks(); 
    myAsyncTask2.execute(); // Works as expected 

雖然它並不需要在此提及,我們必須認識到後的Android SDK版本的蜂窩,如果你運行一個以上的AsyncTask一次,他們居然跑 順序。如果你想並行運行它們,請改用executeOnExecutor。

+0

將'myAsyncTask = new MyAsyncTaks();'然後'myAsyncTask.execute();'工作? – Rahulrr2602

0
在MainActivity

你可以把所以這個:

LeoAsyncTask leoAsyncTaskGeneric; 


public void onClick_AsyncTask(View view) { 

    LeoAsyncTask leoAsyncTaskInner = new LeoAsyncTask(); 
    leoAsyncTaskInner.execute(); 

    leoAsyncTaskGeneric=leoAsyncTaskInner; 

}

/**如果你創建一個在您的AsyncTask類的內存作爲一個通用的一個空間,那麼你可以創建一個實例該方法的onClick內的同一類,有等號,所以你按你的onClick將使用類的AsyncTask的新實例每次,它不會給你帶來麻煩 */

0

線程規則

  • 必須在UI線程上加載AsyncTask類。從JELLY_BEAN開始自動完成 。
  • 任務實例必須在UI線程上創建。 execute(Params ...)必須在UI線程上調用。
  • 不要手動調用onExExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...)。
  • 任務只能一次(如果第二試圖執行一個異常將被拋出。)

執行有關詳細信息請進入這個link

+0

雖然這個鏈接可能回答這個問題,但是在Stack Overflow上只有鏈接的答案是不鼓勵的,你可以通過獲取鏈接的重要部分並將其放入你的答案來改進這個答案,這確保你的答案仍然是一個答案,如果鏈接得到改變或刪除:) – WhatsThePoint