下载图片封装一个工具类,搞定图片批量下载
2013-05-26 22:57
387 查看
在本篇文章中,我们主要介绍下载图片的内容,自我感觉有个不错的建议和大家分享下
项目中用到的,要求一次下载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();
原文链接:
http://www.67tgb.com/?p=590
文章结束给大家分享下程序员的一些笑话语录:
问答
Q:你是怎么区分一个内向的程序员和一个外向的程序员的? A:外向的程序员会看着你的鞋和你说话时。
Q:为什么程序员不能区分万圣节和圣诞节? A:这是因为 Oct 31 == Dec 25!(八进制的 31==十进制的 25)
---------------------------------
原创文章 By
下载和图片
---------------------------------
项目中用到的,要求一次下载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();
原文链接:
http://www.67tgb.com/?p=590
文章结束给大家分享下程序员的一些笑话语录:
问答
Q:你是怎么区分一个内向的程序员和一个外向的程序员的? A:外向的程序员会看着你的鞋和你说话时。
Q:为什么程序员不能区分万圣节和圣诞节? A:这是因为 Oct 31 == Dec 25!(八进制的 31==十进制的 25)
---------------------------------
原创文章 By
下载和图片
---------------------------------
相关文章推荐
- 下载图片封装一个工具类,搞定图片批量下载
- Android开发之使用Handler封装下载图片工具类(源码分享)
- 封装的一个用来下载图片的类
- 封装的一个用来下载图片的类
- 一个无限批量下载百度美女图片的demo
- 封装一个 图片异步下载类
- 写了一个批量下载页面以及页面引用图片的脚本
- 84 Android Hnadler 封装下载图片工具类
- 一个批量下载其它机子图片的c#类(downmoon)
- 封装的一个用来下载图片的类
- 一个用于批量下载网络图片的Shell脚本
- 一个好用的网络图片下载工具类ImageLoader (LruCache一级缓冲机制)
- 一个用于批量下载网络图片的Shell脚本
- PHP--封装一个下载图片的方法
- 毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
- 基于Piccaso的图片下载工具类封装
- 毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
- Unity中如何利用一个协程和www类实现简单的图片下载
- 图片框架Glide 的封装-->工具类
- [置顶] Python3实现批量下载百度搜索图片