2013-01-03 72 views
0

當用戶強制應用程序退出或轉到後臺時,如何清理在AsyncTask中使用的內存,我遇到了一些問題。異步任務內存清理

具體來說,我有一個應用程序使用AsyncTask錄製音頻數據並實時繪製信號。對於錄音,我使用的是AudioRecord類,它需要您開始錄音,然後停止並釋放錄音對象。我的問題是我不知道如何停止和釋放這個對象。

選項我曾想過,想:

  1. 停止在,onStoponDestroy方法釋放的對象,但是這會導致異常。
  2. 停止並釋放方法AsyncTask中的對象。這個問題是我不確定是否在用戶強制退出應用程序時調用此方法,因爲doInBackground方法從未完成。我一直沒有找到任何有關這方面的文件。

AsyncTask如下所示:

 AsyncTask<Void, Void, Void> drawer = new AsyncTask<Void, Void, Void>() { 
     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 

      recorder.startRecording(); 
     } 

     @Override 
     protected Void doInBackground(Void... arg0) { 
      while(true) { 
       int nRead = 0; 
       int offset = 0; 

       while(nRead != readSize) { 
        nRead += recorder.read(buffer, offset + nRead, readSize - nRead); 
       } 

       for(int i = 0; i < readSize; i++) { 
        data[i] = buffer[i];  
       } 

       publishProgress(); 
      }    
     } 

     @Override 
     protected void onProgressUpdate(Void... arg0) { 
      view.setData(data); 
      view.invalidate(); 
     } 
    }; 

代碼的偉大工程,我只是不確定,以確保我正確地清理記錄對象,完全不漏的最好方法。我的困惑是,當UI線程暫停或停止時AsyncTask會發生什麼情況,另外,如果您能夠阻止來自不同線程的對象,則可以盯住它。

任何幫助將不勝感激。
謝謝

+0

**「用戶強制退出應用程序」** - 您如何定義「強制退出」? – Squonk

+0

只需按下後退或主頁按鈕,抱歉,由於沒有準確定義該按鈕。 – lbrendanl

回答

2

OnPostExecute不會被調用,因爲你永遠不會完成你的後臺循環。你需要有一個你退出循環的條件。您可以在UI中設置一個變量,然後檢入後臺任務,或使用取消AsyncTask的功能。

例如,在你的onPause()方法,你可以用drawer.cancel(true);

取消任務然後,在你doInBackground循環,檢查是否該任務已被取消。

if (isCancelled()) { 
    // clean up here 
    break; 
} else { 
    publishProgress(); 
} 

只要您不需要觸摸UI進行清理,此功能就可以工作。如果你需要做UI清理,那麼你可以覆蓋onCancelled方法。

請注意,對於長時間運行的任務,建議您不要使用AsyncTask。所以你可能想看看使用線程。從AsyncTaskdocumentation

AsyncTasks應該理想地(最多。幾秒鐘 )如果您需要保持爲 長時間運行的線程,強烈建議您使用各種可用於短期操作API由 提供的java.util.concurrent pacakge如Executor,ThreadPoolExecutor 和FutureTask。

+0

好吧,看起來不錯,我嘗試過自己實現基本相同的事情,但我不確定AsyncTask會在super.OnPause或super.OnStop完成之前成功完成。謝謝,我會試試這個。 – lbrendanl

+0

由於'AsyncTask'在不同的線程中,它不受'Activity'生命週期的控制。因此,如果需要的話,程序員有義務通知它(例如在這裏使用取消)。 – iagreen

+0

我讀過AsyncTasks是爲了短期任務,所以我嘗試着啓動一個單獨的線程。我的問題是,其他線程不允許觸摸我的UI線程創建的視圖。我需要它能夠觸摸這個,所以我可以調用view.invalidate重繪視圖。但是AsyncTask的線程可以觸及視圖。任何建議更好的設計來處理這個,所以我避免了AsyncTasks? – lbrendanl