圖片批量下載一個Android工具類

jopen 9年前發布 | 11K 次閱讀 Java Android

項目中用到的,要求一次下載30張圖片。開始時使用谷歌bitmap fun中提供的ImageFetcher來下載,但是發現一個蛋疼無比現象,圖片總是莫名其妙的少幾張。

   排除了圖片地址存在無效鏈接外,懷疑是并發下載線程個數太多,線程池滿了以后,使用拋棄策略將以前的下載線程拋棄了。

   求人不如求己,自己寫一個吧。

   在這里使用線程池,支持并發下載。線程池可以自己選擇,使用 newSingleThreadExecutor,newFixedThreadPool,newCachedThreadPool中的任意一種。使用 時,自己實現監聽器,當監聽下載個數與url集合的個數相同時,會回調監聽器的onSuccess()方法。

   源碼如下,希望大家指正

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import android.util.Log;

/**
 * 批量圖片下載類 無需與界面交互的下載類
 *
 * @Description:
 *
 * @author- liubing
 * @create- 2013-5 -6
 * @modify by:
 * @modify- time
 */
public class DownloadService {
     private static String TAG = "DownloadService" ;
     public static final int IO_BUFFER_SIZE = 8 * 1024;
     private static final String CACHE_FILENAME_PREFIX = "cache_";
     private static ExecutorService SINGLE_TASK_EXECUTOR = null;
     private static ExecutorService LIMITED_TASK_EXECUTOR = null;
     private static final ExecutorService FULL_TASK_EXECUTOR = null;
     private static final ExecutorService DEFAULT_TASK_EXECUTOR ;
     private static Object lock = new Object();
     static {
           // SINGLE_TASK_EXECUTOR = (ExecutorService)
           // Executors.newSingleThreadExecutor();
           LIMITED_TASK_EXECUTOR = (ExecutorService) Executors
                   . newFixedThreadPool(1);
           // FULL_TASK_EXECUTOR = (ExecutorService)
           // Executors.newCachedThreadPool();
           DEFAULT_TASK_EXECUTOR = LIMITED_TASK_EXECUTOR ;
     };
     // 下載狀態監聽,提供回調
     DownloadStateListener listener;
     // 下載目錄
     private String downloadPath;

     // 下載鏈接集合
     private List<String> listURL;
     // 下載個數
     private int size = 0;

     // 下載完成回調接口
     public interface DownloadStateListener {
           public void onFinish();

           public void onFailed();
     }

     public DownloadService(String downloadPath, List<String> listURL,
              DownloadStateListener listener) {
           this.downloadPath = downloadPath;
           this.listURL = listURL;
           this.listener = listener;
     }

     /**
      * 暫未提供設置
      */
     public void setDefaultExecutor() {

     }

     /**
      * 開始下載
      */
     public void startDownload() {
           // 首先檢測path是否存在
          File downloadDirectory = new File(downloadPath );
           if (!downloadDirectory.exists()) {
              downloadDirectory.mkdirs();
          }

           for (final String url : listURL) {
               //捕獲線程池拒絕執行異常
               try {
                    // 線程放入線程池
                    DEFAULT_TASK_EXECUTOR.execute(new Runnable() {

                         @Override
                         public void run() {
                             downloadBitmap(url);
                        }
                   });
              } catch (RejectedExecutionException e) {
                   e.printStackTrace();
                   Log. e(TAG, "thread pool rejected error");
                    listener.onFailed();
              } catch (Exception e) {
                   e.printStackTrace();
                    listener.onFailed();
              }

          }

     }

     /**
      * 下載圖片
      *
      * @param urlString
      * @return
      */
     private File downloadBitmap(String urlString) {
          String fileName = urlString;
           // 圖片命名方式
           final File cacheFile = new File(createFilePath(new File(
                    downloadPath), fileName));

          HttpURLConnection urlConnection = null;
          BufferedOutputStream out = null;

           try {
               final URL url = new URL(urlString);
              urlConnection = (HttpURLConnection) url.openConnection();
               final InputStream in = new BufferedInputStream(
                        urlConnection.getInputStream(), IO_BUFFER_SIZE);
              out = new BufferedOutputStream(new FileOutputStream(cacheFile),
                         IO_BUFFER_SIZE);

               int b;
               while ((b = in.read()) != -1) {
                   out.write(b);
              }
               // 每下載成功一個,統計一下圖片個數
              statDownloadNum();
               return cacheFile;

          } catch (final IOException e) {
               // 有一個下載失敗,則表示批量下載沒有成功
              Log. e(TAG, "download " + urlString + " error");
               listener.onFailed();

          } finally {
               if (urlConnection != null) {
                   urlConnection.disconnect();
              }
               if (out != null ) {
                    try {
                        out.close();
                   } catch (final IOException e) {
                        Log. e(TAG, "Error in downloadBitmap - " + e);
                   }
              }
          }

           return null ;
     }

     /**
      * Creates a constant cache file path given a target cache directory and an
      * image key.
      *
      * @param cacheDir
      * @param key
      * @return
      */
     public static String createFilePath(File cacheDir, String key) {
           try {
               // Use URLEncoder to ensure we have a valid filename, a tad hacky
               // but it will do for
               // this example
               return cacheDir.getAbsolutePath() + File.separator + CACHE_FILENAME_PREFIX
                        + URLEncoder.encode(key.replace("*", ""), "UTF-8" );
          } catch (final UnsupportedEncodingException e) {
              Log. e(TAG, "createFilePath - " + e);
          }

           return null ;
     }


     /**
      * 統計下載個數
      */
     private void statDownloadNum() {
           synchronized (lock ) {
               size++;
               if (size == listURL .size()) {
                   Log. d(TAG, "download finished total " + size);
                    // 釋放資源
                    DEFAULT_TASK_EXECUTOR.shutdownNow();
                    // 如果下載成功的個數與列表中 url個數一致,說明下載成功
                    listener.onFinish(); // 下載成功回調
              }
          }
     }
}

使用方法如下:

new DownloadService( "/mnt/sdcard/test", listUrl, new DownloadStateListener() {

               @Override
               public void onFinish() {
                    //圖片下載成功后,實現您的代碼

              }

               @Override
               public void onFailed() {
                    //圖片下載成功后,實現您的代碼

              }
          }).startDownload();

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!