封装一个工具类,搞定图片批量下载
来源:互联网 发布:墙面互动投影软件 编辑:程序博客网 时间:2024/05/21 09:42
项目中用到的,要求一次下载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
转载注明:望月听涛
- 封装一个工具类,搞定图片批量下载
- 封装一个 图片异步下载类
- 封装的工具类(网络获取Json,图片,下载图片,下载Mp3,下载视频)
- 84 Android Hnadler 封装下载图片工具类
- 一个批量下载图片的c#类(downmoon)
- 一个批量下载其它机子图片的c#类(downmoon)
- 封装的一个用来下载图片的类
- PHP--封装一个下载图片的方法
- 封装一个SqliteDataBase工具类
- Android开发之使用Handler封装下载图片工具类(源代码分享)
- sftp 下载 批量下载,单个下载,工具类
- php 批量下载图片的一个小程序
- 一个用于批量下载网络图片的Shell脚本
- 一个用于批量下载网络图片的Shell脚本
- 一个无限批量下载百度美女图片的demo
- php 批量下载图片的一个小程序
- Python批量下载图片
- 批量下载大量图片
- 转】struts2的s:iterator 标签 详解
- 【总结】css常见两列布局方案
- WCF WebGet WebInvoke WCF Jquery 调用
- MFC和Win32的区别
- cmd中格式化时间
- 封装一个工具类,搞定图片批量下载
- 匹配IP字串、域名的正则表达式
- 关于ligerGrid中的detail明细属性
- Web 前端开发精华文章推荐(jQuery、HTML5、CSS3)【系列十五】
- 递归和迭代的区别
- ORM(Object Relational Mapping, 对象关系映射)简介
- hdu 2553 (N皇后)
- 一个硕士生怎么在一面内发五篇SCI
- div 中的img垂直、水平剧中