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