批量下载大量图片

最近由于项目需要,我们要在某个地方一次下载大量的图片,并且将这些图片存放到SD卡中,将地址保存在数据库中,为了保证下载速度和程序运行的效率,我们考虑了以下几个问题:

1.为了保证操作效率,每张图片的下载和存储过程需要单独使用一个线程。

2.需要记录有几张图片下载成功,几张图片下载失败。

3.需要知道什么时候所有的图片下载任务结束。

4.为了保证CPU利用率,我们需要控制同一时刻最多可以开启多少线程。


对于问题1,开启线程下载图片的话,我们可以新建一个Thread()对象来进行图片下载的相关处理,多张图片可以进行循环开启线程,逻辑如下:

for(int i = 0;i < taskCount;i++){
new Thread(new Runnable(){
        @override
	public void run(){
	//下载图片代码
	...
	//将图片存入SD卡的代码
	...
	//将图片地址存入数据库的代码
	...
	}
}).start();
}



对于问题2,我们可以设置几个变量来记录图片的下载情况

int totalTask;//一共需要下载多少张图片
int okTask;//成功的任务
int failTask;//失败的任务
这样,在使用的时候,我们可以

new Thread(new Runnable(){
        @override
	public void run(){
	//下载图片代码
	Bitmap bm = downloadPic(url);
        if(bm != null){
            //将图片存入SD卡的代码
	    ...
	    //将图片地址存入数据库的代码
	    ...
            okTask++;

        }else {
             failTask++;
         }
	
	}
}).start();

问题3,判断什么时候所有任务才算结束,这就可以利用问题2中的3个变量,我们定义一个实时监听下载完成状态的方法

isDownloadComplete(final CompleteCallback callback){
		    new Thread(new Runnable() {
		    @Override
			public void run() {
		    	//这个循环等待所有任务完成
		    	while(okTask + failTask < totalTask);
		    	if(okTask == totalTask){
		    		//所有图片下载成功
		    		callback.onComplete();
		    	} else {
		    		//有些图片没有下载成功
		    		callback.onFail();
		    	}
		    }
		}


回调的接口定义:

public interface CompleteCallback {
		public void onComplete();

		public void onFail();
	}

第四个问题,也是一个很重要的问题,对于这个问题,我们可以将问题1中的循环开启多个线程改为用线程池对线程进行操作,这样既控制了同时启动的线程数量,又可以更好的管理启动的线程。

建立线程池,我们使用的是android 所带的ExecutorService ,关于这个服务,请参考下面的文章:

http://blog.csdn.net/hudashi/article/details/7008583

http://blog.sina.com.cn/s/blog_6151984a0100krj8.html

这样,问题1中的代码可以改为:

//nThreads 代表当前可以开启的线程数量
public void downloadPic() {
    ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
    for(int i = 0;i < totalTask;i++){
        executorService.submit(new Runnable() {
	    @Override
	    public void run() {
	        //下载图片代码
	        Bitmap bm = downloadPic(url);
                if(bm != null){
                    //将图片存入SD卡的代码
	            ...
	            //将图片地址存入数据库的代码
	            ...
                    okTask++;

                }else {
                    failTask++;
                }
	
            }
        }
    }
}

 这样,我们就实现了一个批量下载图片的大体框架,我们假设将上述的过程封装成了一个类,那么我们在使用时就可以: 

BitmapDownloadHelper helper = new BitmapDownloadHelper(需要传入的url数据等);
//这个就是上面的下载过程
helper.downloadPic();
helper.isDownloadComplete(new CompleteCallback(){
    @override
    public void onComplete(){
        //下载成功的后续处理
    }
    @override
    public void onFail(){
        //下载失败的后续处理
    }
});

 

好了,就写到这里,如有错误或者补充,还望不吝赐教。



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
运行环境 .NET Framework2.0 开发工具 Microsoft Visual Studio 2005 二. 部分代码说明(主要讲解异步分析和下载): 异步分析下载采取的策略是同时分析同时下载,即未等待数据全部分析完毕就开始把已经分析出来的图片链接开始下载下载成功的均在List框链接前面划上了√ ,未能下载图片有可能是分析错误或者是下载异常。 1. 异步分析部分代码 /// /// 异步分析下载 /// private void AsyncAnalyzeAndDownload(string url, string savePath) { this.uriString = url; this.savePath = savePath; #region 分析计时开始 count = 0; count1 = 0; freq = 0; result = 0; QueryPerformanceFrequency(ref freq); QueryPerformanceCounter(ref count); #endregion using (WebClient wClient = new WebClient()) { AutoResetEvent waiter = new AutoResetEvent(false); wClient.Credentials = CredentialCache.DefaultCredentials; wClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(AsyncURIAnalyze); wClient.DownloadDataAsync(new Uri(uriString), waiter); //waiter.WaitOne(); //阻止当前线程,直到收到信号 } } /// /// 异步分析 /// protected void AsyncURIAnalyze(Object sender, DownloadDataCompletedEventArgs e) { AutoResetEvent waiter = (AutoResetEvent)e.UserState; try { if (!e.Cancelled && e.Error == null) { string dnDir = string.Empty; string domainName = string.Empty; string uri = uriString; //获得域名 http://www.sina.com/ Match match = Regex.Match(uri, @"((http(s)?://)?)+[\w-.]+[^/]");//, RegexOptions.IgnoreCase domainName = match.Value; //获得域名最深层目录 http://www.sina.com/mail/ if (domainName.Equals(uri

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值