/* * Copyright (C) 2013 www.418log.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.bitmap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import android.os.Handler; import android.os.Message; import android.util.Log; import com.ab.global.AbAppData; import com.ab.util.AbAppUtil; import com.ab.util.AbFileUtil; import com.ab.util.AbStrUtil; // TODO: Auto-generated Javadoc /** * * Copyright (c) 2012 All rights reserved * 名称:AbImageDownload.java * 描述:线程池图片下载 * @author zhaoqp * @date:2013-5-23 上午10:10:53 * @version v1.0 */ public class AbImageDownloadPool{ /** The tag. */ private static String TAG = "AbImageDownloadPool"; /** The Constant D. */ private static final boolean D = AbAppData.DEBUG; //单例对象 /** The image download. */ private static AbImageDownloadPool imageDownload = null; /** 固定3个线程来执行任务 . */ private static int nThreads = 3; /** The executor service. */ private ExecutorService executorService = null; /** 下载完成后的消息句柄. */ private static Handler handler = new Handler() { @Override public void handleMessage(Message msg) { AbImageDownloadItem item = (AbImageDownloadItem)msg.obj; item.listener.update(item.bitmap, item.imageUrl); } }; /** * 构造图片下载器. * * @param nThreads the n threads */ protected AbImageDownloadPool(int nThreads) { executorService = Executors.newFixedThreadPool(nThreads); } /** * 单例构造图片下载器. * * @return single instance of AbImageDownloadPool */ public static AbImageDownloadPool getInstance() { if (imageDownload == null) { nThreads = AbAppUtil.getNumCores(); imageDownload = new AbImageDownloadPool(nThreads*3); } return imageDownload; } /** * Download. * * @param item the item */ public void download(final AbImageDownloadItem item) { String imageUrl = item.imageUrl; if(AbStrUtil.isEmpty(imageUrl)){ if(D)Log.d(TAG, "图片URL为空,请先判断"); }else{ imageUrl = imageUrl.trim(); } //从缓存中获取图片 final String cacheKey = AbImageCache.getCacheKey(imageUrl, item.width, item.height, item.type); item.bitmap = AbImageCache.getBitmapFromCache(cacheKey); if(item.bitmap == null){ // 缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中 executorService.submit(new Runnable() { public void run() { try { //逻辑:判断这个任务是否有其他线程再执行,如果有等待,直到下载完成唤醒显示 Runnable runnable = AbImageCache.getRunRunnableFromCache(cacheKey); if(runnable != null){ //线程等待通知后显示 if(D) Log.d(TAG, "等待:"+cacheKey+","+item.imageUrl); AbImageCache.addToWaitRunnableCache(cacheKey, this); synchronized(this){ this.wait(); } if(D) Log.d(TAG, "我醒了:"+item.imageUrl); //直接获取 item.bitmap = AbImageCache.getBitmapFromCache(cacheKey); }else{ //增加下载中的线程记录 if(D) Log.d(TAG, "增加图片下载中:"+cacheKey+","+item.imageUrl); AbImageCache.addToRunRunnableCache(cacheKey, this); item.bitmap = AbFileUtil.getBitmapFromSDCache(item.imageUrl,item.type,item.width,item.height); //增加到下载完成的缓存,删除下载中的记录和等待的记录,同时唤醒所有等待列表中key与其key相同的线程 AbImageCache.addBitmapToCache(cacheKey,item.bitmap); } } catch (Exception e) { if(D) Log.d(TAG, "error:"+item.imageUrl); e.printStackTrace(); } finally{ if (item.listener != null) { Message msg = handler.obtainMessage(); msg.obj = item; handler.sendMessage(msg); } } } }); }else{ if(D) Log.d(TAG, "从内存缓存中得到图片:"+cacheKey+","+item.bitmap); if (item.listener != null) { Message msg = handler.obtainMessage(); msg.obj = item; handler.sendMessage(msg); } } } /** * 描述:立即关闭. */ public void shutdownNow(){ if(!executorService.isTerminated()){ executorService.shutdownNow(); listenShutdown(); } } /** * 描述:平滑关闭. */ public void shutdown(){ if(!executorService.isTerminated()){ executorService.shutdown(); listenShutdown(); } } /** * 描述:关闭监听. */ public void listenShutdown(){ try { while(!executorService.awaitTermination(1, TimeUnit.MILLISECONDS)) { if(D) Log.d(TAG, "线程池未关闭"); } if(D) Log.d(TAG, "线程池已关闭"); } catch (Exception e) { e.printStackTrace(); } } }