2013-05-15 44 views
0

我有一個應用程序,用戶可能需要下載最多760個文件,總計大約350MB。這是不是可能壓縮這些文件,它們必須作爲鬆散的文件下載!用於異步下載數百個文件的解決方案

我目前使用Android Asynchronous Http Client下載單個文件,而AsyncTask運行整個過程。

這裏有一個DownloadThread對象,處理下載數百個文件在後臺的一個例子:

public class DownloadThread extends AsyncTask<String,String,String> { 

ArrayList<String> list; 
AsyncHttpClient client; 
String[] allowedContentTypes = new String[] { "audio/mpeg" }; 
BufferedOutputStream bos; 
FileOutputStream fos; 

@Override 
protected String doInBackground(String... params) { 
    DownloadTask task; 
    for (String file : list) { 
     //the "list" variable has already been populated with hundreds of strings 
     task = new DownloadTask(file); 
     task.execute(""); 
     while (!task.isdone) 
      try { 
       Thread.sleep(10); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
    } 

    return null; 
} 


class DownloadTask extends AsyncTask<String, String, String> { 

    String character, filename; 
    boolean isdone = false; 

    public DownloadTask(String file) { 
     //file = something like "Whale/sadwhale.mp3" 
     character = file.split("/")[0]; 
     filename = file.split("/")[1]; 
    } 

    @Override 
    protected void onPreExecute() { 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     if (!result.equals("Error")) { 
         //Do something on success 
     } 
     isdone = true; 
    } 

    @Override 
    protected String doInBackground(String... str) { 
     client = new AsyncHttpClient(); 
     client.get("http://some-site.com/sounds/" + character + "/" 
       + filename, new BinaryHttpResponseHandler(
       allowedContentTypes) { 
      @Override 
      public void onSuccess(byte[] fileData) { 
       try { 
        // Make file/folder and create stream 
        File folder = new File(Environment 
          .getExternalStorageDirectory() 
          + CharSelect.directory + character); 
        folder.mkdirs(); 
        File dest = new File(folder, filename); 
        fos = new FileOutputStream(dest); 
        bos = new BufferedOutputStream(fos); 
        // Transfer data to file 
        bos.write(fileData); 
        bos.flush(); 
        bos.close(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
     return "Success"; 
    } 

} 

}

DownloadThread在後臺運行,並呼籲數以百計它自己AsyncTasks的。它會等待任務完成下載,然後繼續執行每個下載的for循環。

這工作,有點。某些下載似乎無法正常完成或根本無法啓動。在760次下載列表中,平均100次下載完成正確,我必須重新啓動該過程再下載另外100次下載,直到該次下載失敗。我有一種感覺,這是由於計時問題,因爲Thread.sleep(10)行似乎有點「hackish」。

當然,從另一個AsyncTask調用數百個AsyncTasks並不是實現此目的最有效的方法。我如何更改此代碼或實施第三方解決方案以適應此任務?

+0

他們真的需要異步下載嗎?我覺得把他們放在隊列中,一次下載一個就沒問題。 – FDinoff

+0

它並沒有_have_,但通過這種異步操作,我可以(最終)一次管理2或3次下載,從而提高整體速度。當然,我首先需要一個可靠的方法。 – Snailer

回答

3

試用DownloadManager API。這應該是你需要的。

+0

我沒有意識到這是建在O_O一定會看看! – Snailer

1

以下是您需要記住的事項:

計算機資源有限;網絡帶寬,CPU,內存,磁盤等

是下載1個文件在同一時間對760文件的時間同時不能拿邏輯比同時下載任何更長的時間。

然而,通過產生一大堆的後臺任務/線程你招致了很多線程顛簸/開銷每一個需要是上下文切換和縮小。 CPU帶寬將在交換中消耗,而不是真正將數據移入或移出網絡接口。另外,每個線程都會佔用自己的內存,如果不是池的一部分,可能需要創建它。

基本上你的應用程序無法正常工作可靠/在所有的原因是幾乎可以肯定,因爲它的運行了CPU /硬盤IO /內存資源,它完成下載或充分利用網絡以及之前。

解決方法:找到一個圖書館要做到這一點,或使用類執行人套件和使用線程池有限(那麼只有在下載時數)。

這裏是你試圖做什麼野生一些好的跡象,不建議:

  • 谷歌玩的更新都是系列化
  • 亞馬遜的MP3文件下載是完全系列化
  • 默認在Linux中SCP客戶端序列化的文件傳輸
  • 的Windows更新的下載順序

戈拍照嗎?甩掉所有這些線程是提高感知速度的回報。