2010-11-02 109 views
32

我遇到了AsyncTask類的問題。看起來我的任務在創建4或5個任務後停止工作。AsyncTask doInBackground不運行

我有2項活動。 MainActivity只保存一個按鈕來啓動名爲​​ImageActivity的第二個活動。

ImageActivity非常簡單。它得到了一個設置佈局的onCreate,然後它啓動一個新的AsyncTask,從Internet上加載一個圖像。這在前幾次運作良好。但比它突然停止工作。 onPreExecute方法每次運行,但不是doInBackground方法。我試圖用睡眠循環來簡化doInBackground,並且發生同樣的事情。我無法理解這種行爲,因爲asynctask在onDestroy方法中都被取消並設置爲null。所以每次我開始一個新的ImageActivity,我也創建一個新的AsyncTask。

我通過點擊後退按鈕並單擊MainActivity上的按鈕來重新創建ImageActivity和任務。

任何想法的人?我真的很苦惱這個。

UPDATE:代碼用於啓動ImageActivity

Intent intent = new Intent(); 
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); 
intent.setClassName(this, ImageActivity.class.getName()); 
startActivity(intent); 

上面的代碼開始該活性(一個按鈕onClickListener內部)

public class ImageActivity extends Activity { 

    private AsyncTask<Void, Void, Void> task; 

    public void onCreate(Bundle bundle) { 
     super.onCreate(bundle); 
     setContentView(R.layout.main); 

     task = new AsyncTask<Void, Void, Void>() { 

      @Override 
      protected void onPreExecute() 
      { 
       Log.d(TAG, "onPreExecute()"); 
      } 

      @Override 
      protected Void doInBackground(Void... params) 
      { 
       Log.d(TAG, "doInBackground() -- Here is the download"); 
       // downloadBitmap("http://mydomain.com/image.jpg") 
       return null; 
      } 

      @Override 
      protected void onPostExecute(Void res) 
      { 
       Log.d(TAG, "onPostExecute()"); 
       if(isCancelled()){ 
        return; 
       } 
      } 
     }.execute(); 
    } 

    @Override 
    protected void onDestroy() 
    { 
     super.onDestroy(); 
     task.cancel(true); 
    } 
} 

UPDATE:

我已經採用的組合測試傳統的線程和runOnUiThread方法,它似乎更好。現在線程每次都運行。

+0

發佈您的代碼。你打電話過得怎麼樣?我們不知道如何在沒有代碼的情況下幫助您 – Falmarri 2010-11-02 19:07:37

+0

完全相同的問題是,在我的應用程序中啓動多個AsyncTasks後,該應用程序僅執行onPreExecute(),但未輸入doInBackground()。嘗試你的線程方法現在.. – 2011-11-20 08:43:51

+1

我有同樣的問題。奇怪的是,它因設備而異。它發生在平板電腦(Android 4.0)上,但運行完全相同的代碼的手機(Android 2.3.4)沒有它。 – Hong 2012-07-06 22:14:39

回答

22

拆除的AsyncTask,並使用它,而不是用runOnUiThread似乎工作相結合的傳統主題。但是我仍然沒有找到AsyncTask如此「不穩定」的原因。

下面是對我的作品的代碼:

public class ImageActivity extends Activity { 

    private Thread worker; 

    public void onCreate(Bundle bundle) { 
     super.onCreate(bundle); 
     setContentView(R.layout.main); 

     worker = new Thread(new Runnable(){ 

      private void updateUI(final List<Object> list) 
      { 
       if(worker.isInterrupted()){ 
        return; 
       } 
       runOnUiThread(new Runnable(){ 

        @Override 
        public void run() 
        { 
         // Update view and remove loading spinner etc... 
        } 
       }); 
      } 

      private List<Object> download() 
      { 
       // Simulate download 
       SystemClock.sleep(1000); 
       return new ArrayList<Object>(); 
      } 

      @Override 
      public void run() 
      { 
       Log.d(TAG, "Thread run()"); 
       updateUI(download()); 
      } 

     }); 
     worker.start(); } 

    @Override 
    protected void onDestroy() 
    { 
     super.onDestroy(); 
     worker.interrupt(); 
    } 
} 
+1

謝謝,我也遇到了同樣的問題(在這裏發佈了它,但它沒有解決問題)谷歌搜索把我帶到這裏:) – Ryan 2011-09-29 17:02:02

+5

這說明了爲什麼AsyncTask可能失敗了你(和我!): http://foo.jasonhudgins.com/2010/05/limitations-of-asynctask.html – Archie1986 2011-12-05 18:00:29

+0

只是分享一個想法,我最近遇到了類似'AsyncTask'的行爲的巫術。然而,我在後臺關閉了一個已經運行的'AsyncTask'之後,我已經過去了。很奇怪,但它對我有用。 – faizanjehangir 2014-04-04 08:16:11

0

您應該不必擔心Android中的管家線程,因爲它由系統管理。

請同時發佈圖片下載方法。你是否也嘗試不取消onDestroy()方法中的線程?你如何將圖像返回到你的UI線程?

+0

downloadBitmap方法有點長,並不是問題。我遇到同樣的問題,如果我嘗試Thread.sleep(5000)模擬緩慢的下載。當我使用Thread.sleep時,我可以啓動ImageActivity 3-4次,任務工作。之後,該任務僅打印「預執行」而不打印「doInBackground」日誌消息,這意味着它不會由於某種原因而被調用。是的,我試圖不取消任務,但我沒有幫助。 – 2010-11-02 23:35:38

+0

是否有更多的代碼被省略? – 2010-11-03 08:11:42

0

我相信這個問題是與重圖像下載任務。即使您取消異步任務,圖像下載仍將繼續執行,異步任務不會完成,直到下載完成。您可能希望在下載正在進行時檢查AyncTask上的isCancelled()方法,並在任務被取消時終止下載。

僅供參考,請參閱有關cancel()方法的文檔: 嘗試取消執行此任務。如果任務已完成,已被取消或因其他原因無法取消,此嘗試將失敗。如果成功,並且此任務在調用取消時尚未開始,則此任務不應運行。如果任務已經開始,則mayInterruptIfRunning參數確定執行此任務的線程是否應該中斷以試圖停止任務。 調用此方法將導致在doInBackground(Object [])返回後在UI線程上調用onCancelled(Object)。調用此方法可確保永不調用onPostExecute(Object)。調用此方法後,應該從doInBackground(Object [])中定期檢查isCancelled()返回的值,以儘早完成任務。

1

使用traceview來調查 - 或獲取線程轉儲。我的猜測是你的一個AsyncTask線程正在下載。

AsyncTask有一個小的線程池,所以如果你的一個任務掛起,它可能最終會阻塞你的線程池。

下面是一個可以運行的快速測試 - 4.3,我看到我只能運行5個併發線程。當一個線程退出時,其他線程啓動。

private void testAsyncTasks() { 

     for (int i = 1; i <= 10; i++) { 
       final int tid = i; 
       new AsyncTask<Integer, Void, Void>() { 
        protected void onPreExecute() { 
          Log.d("ASYNCTASK", "Pre execute for task : " + tid); 
        }; 

        @Override 
        protected Void doInBackground(Integer... args) { 
          int taskid = args[0]; 
          long started = SystemClock.elapsedRealtime(); 
          Log.d("ASYNCTASK", "Executing task: " + taskid + " at " + started); 
          for (int j = 1; j <= 20; j++) { 
           Log.d("ASYNCTASK", " task " + taskid + ", time=" + (SystemClock.elapsedRealtime() - started)); 
           SystemClock.sleep(1000); 
          } 
          return null; 
        } 

        protected void onPostExecute(Void result) { 
          Log.d("ASYNCTASK", "Post execute for task : " + tid); 
        }; 
       }.execute(i); 

     } 
    } 
0

我也有這個,沒有真正的理由不開始。我注意到,重新啓動adb後,它再次工作。不知道這是爲什麼,但它確實爲我工作

5

我剛剛遇到了這個問題。如果你使用AsyncTask.execute,你的任務是在一個串行隊列(從Android 4.3源)運行:

當第一次推出,AsyncTasks是在單個 後臺線程串行執行。從DONUT開始,將其更改爲允許多個任務並行操作的 線程池。從 HONEYCOMB開始,任務在單個線程上執行,以避免並行執行導致的常見應用程序錯誤 。

這與我看到的行爲一致。我有一個AsyncTask彈出一個對話框doInBackground並阻止,直到對話框關閉。該對話框需要自己的AsyncTask來完成。對話框的AsyncTask.doInBackground方法從未執行,因爲原始AsyncTask仍然被阻止。

解決方法是在單獨的Executor中執行第二個AsyncTask

+0

doInBackground()不應該調用UI方法(例如,像你提到的那樣彈出一個對話框)。 – 2014-03-27 07:51:17

+0

我在主線程中顯示了對話框,但它是由'doInBackground'觸發的。 – 2014-03-27 14:36:12

+1

這是應該接受的正確答案。 (剛剛完成了我對這個主題的調查,得出了相同的結論 - 單獨的執行程序) – 2014-07-24 02:18:25

相關問題