/* * 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.ArrayList; import java.util.List; import android.os.Handler; import android.os.Message; import android.util.Log; import com.ab.global.AbAppData; import com.ab.util.AbFileUtil; import com.ab.util.AbStrUtil; // TODO: Auto-generated Javadoc /** * 描述:图片下载线程,按队列下载(先检查SD卡是否存在相同文件,不存在则下载,最后再从SD卡中读取). * * @author zhaoqp * @date 2011-12-10 * @version v1.0 */ public class AbImageDownloadQueue extends Thread { /** The tag. */ private static String TAG = "AbImageDownloadQueue"; /** The Constant D. */ private static final boolean D = AbAppData.DEBUG; /** 下载队列. */ private List<AbImageDownloadItem> queue; /** 图片下载线程单例类. */ private static AbImageDownloadQueue imageDownloadThread = null; /** 控制释放. */ private static boolean stop = false; /** 下载完成后的消息句柄. */ private static Handler handler = new Handler() { @Override public void handleMessage(Message msg) { //if(D)Log.d(TAG, "任务callback handleMessage..."); AbImageDownloadItem item = (AbImageDownloadItem)msg.obj; item.listener.update(item.bitmap, item.imageUrl); } }; /** * 构造图片下载线程队列. */ private AbImageDownloadQueue() { stop = false; queue = new ArrayList<AbImageDownloadItem>(); } /** * 单例构造图片下载线程. * * @return single instance of AbImageDownloadQueue */ public static AbImageDownloadQueue getInstance() { if (imageDownloadThread == null) { imageDownloadThread = new AbImageDownloadQueue(); imageDownloadThread.setName("AbImageDownloadQueue-1"); //创建后立刻运行 imageDownloadThread.start(); } return imageDownloadThread; } /** * 开始一个下载任务. * * @param item 图片下载单位 * @return Bitmap 下载完成后得到的Bitmap */ public void download(AbImageDownloadItem item) { //检查图片路径 String imageUrl = item.imageUrl; if(AbStrUtil.isEmpty(imageUrl)){ if(D)Log.d(TAG, "图片URL为空,请先判断"); }else{ imageUrl = imageUrl.trim(); } //从缓存中获取这个Bitmap. String cacheKey = AbImageCache.getCacheKey(imageUrl, item.width, item.height, item.type); item.bitmap = AbImageCache.getBitmapFromCache(cacheKey); if(item.bitmap == null){ addDownloadItem(item); }else{ if(D) Log.d(TAG, "从内存缓存中得到图片:"+cacheKey+","+item.bitmap); if (item.listener != null) { Message msg = handler.obtainMessage(); msg.obj = item; handler.sendMessage(msg); } } } /** * 描述:添加到图片下载线程队列. * * @param item 图片下载单位 */ private synchronized void addDownloadItem(AbImageDownloadItem item) { queue.add(item); //添加了下载项就激活本线程 this.notify(); } /** * 开始一个下载任务并清除原来队列. * * @param item 下载单位 */ public void downloadBeforeClean(AbImageDownloadItem item) { queue.clear(); addDownloadItem(item); } /** * 描述:线程运行. * * @see java.lang.Thread#run() */ @Override public void run() { while(!stop) { try { if(D)Log.d(TAG, "图片下载队列大小:"+queue.size()); while(queue.size() > 0) { AbImageDownloadItem item = queue.remove(0); //缓存图片路径 String cacheKey = AbImageCache.getCacheKey(item.imageUrl, item.width, item.height, item.type); //逻辑:判断这个任务是否有其他线程再执行,如果有等待,直到下载完成唤醒显示 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); } //需要执行回调来显示图片 if (item.listener != null) { //交由UI线程处理 Message msg = handler.obtainMessage(); msg.obj = item; handler.sendMessage(msg); } } //停止 if(stop){ queue.clear(); return; } //没有下载项时等待 synchronized(this) { this.wait(); } } catch (Exception e) { e.printStackTrace(); }finally{ } } } /** * * 描述:终止队列释放线程 * @throws */ public void stopQueue(){ try { stop = true; imageDownloadThread = null; this.interrupt(); } catch (Exception e) { e.printStackTrace(); } } }