/*
* 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.HashMap;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.util.Log;
import com.ab.global.AbAppData;
import com.ab.util.AbMd5;
import com.ab.util.AbStrUtil;
// TODO: Auto-generated Javadoc
/**
* 描述:图片缓存.
*
* @author zhaoqp
* @date:2013-5-23 上午10:10:53
* @version v1.0
*/
public class AbImageCache {
/** The tag. */
private static String TAG = "AbImageCache";
/** The Constant D. */
private static final boolean D = AbAppData.DEBUG;
/** 缓存空间大小8MB. */
public static int cacheSize = 8 * 1024 * 1024;
/** 为了加快速度,在内存中开启缓存,最新的LruCache. */
private static final LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
@Override
protected void entryRemoved(boolean evicted, String key,
Bitmap oldValue, Bitmap newValue) {
if(D) Log.d(TAG, "LruCache:移除了"+key);
}
};
/**正在下载中的线程*/
private static final HashMap<String, Runnable> runRunnableCache = new HashMap<String, Runnable>();
/**等待中的线程*/
private static final List<HashMap<String, Runnable>> waitRunnableList = new ArrayList<HashMap<String, Runnable>>();
/**锁对象*/
public static final ReentrantLock lock = new ReentrantLock();
/**
* 描述:从缓存中获取这个Bitmap.
*
* @param key the key
* @return the bitmap from mem cache
*/
public static Bitmap getBitmapFromCache(String key) {
return bitmapCache.get(key);
}
/**
* 描述:增加一个图片到缓存.
*
* @param key 通过url计算的缓存key
* @param bitmap the bitmap
*/
public static void addBitmapToCache(String key,Bitmap bitmap){
try {
if(D) Log.d(TAG, "图片下载完成:"+key);
lock.lock();
if(AbStrUtil.isEmpty(key)){
return;
}
if (getBitmapFromCache(key) == null && bitmap!=null) {
bitmapCache.put(key, bitmap);
if(D) Log.d(TAG, "存入缓存:"+key+","+bitmap);
if(D) Log.d(TAG, "测试存入缓存是否成功:"+key+","+getBitmapFromCache(key));
}
//表示下载中的缓存清除
removeRunRunnableFromCache(key);
if(D) Log.d(TAG, "检查挂起线程:"+waitRunnableList.size());
//唤醒等待线程并移除列表
removeWaitRunnableFromCache(key);
} catch (Exception e) {
e.printStackTrace();
} finally{
lock.unlock();
}
}
/**
* 描述:从缓存删除.
*
* @param key 通过url计算的缓存key
*/
public static void removeBitmapFromCache(String key){
try {
lock.lock();
if (getBitmapFromCache(key) != null) {
bitmapCache.remove(key);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
lock.unlock();
}
}
/**
* 描述:清空缓存的Bitmap.
*/
public static void removeAllBitmapFromCache() {
bitmapCache.evictAll();
}
/**
* 根据url计算缓存key,这个key+后缀就是文件名.
* @param url 图片地址.
* @param width 图片宽度.
* @param height 图片高度.
* @param type 处理类型.
*/
public static String getCacheKey(String url, int width, int height,int type) {
return AbMd5.MD5(new StringBuilder(url.length() + 12).append("#W").append(width)
.append("#H").append(height).append("#T").append(type).append(url).toString());
}
/**
* 描述:从缓存中获取这个正在执行线程.
*
* @param key the key
* @return the runnable
*/
public static Runnable getRunRunnableFromCache(String key) {
return runRunnableCache.get(key);
}
/**
* 描述:增加一个正在执行线程的记录.
*
* @param key 通过url计算的缓存key
* @param runnable the runnable
*/
public static void addToRunRunnableCache(String key,Runnable runnable){
try {
lock.lock();
if(AbStrUtil.isEmpty(key) || runnable == null){
return;
}
if (getRunRunnableFromCache(key) == null) {
runRunnableCache.put(key, runnable);
}
}catch (Exception e) {
e.printStackTrace();
} finally{
lock.unlock();
}
}
/**
* 描述:从缓存一个正在执行的线程.
*
* @param key 通过url计算的缓存key
*/
public static void removeRunRunnableFromCache(String key){
if (getRunRunnableFromCache(key) != null) {
runRunnableCache.remove(key);
}
}
/**
* 描述:从缓存中获取这个正在等待线程.
*
* @param key the key
* @return the runnable
*/
public static Runnable getWaitRunnableFromCache(String key) {
return runRunnableCache.get(key);
}
/**
* 描述:增加一个等待线程的记录.
*
* @param key 通过url计算的缓存key
* @param runnable the runnable
*/
public static void addToWaitRunnableCache(String key,Runnable runnable){
try {
lock.lock();
if(AbStrUtil.isEmpty(key) || runnable == null){
return;
}
HashMap<String, Runnable> runnableMap = new HashMap<String, Runnable>();
runnableMap.put(key, runnable);
waitRunnableList.add(runnableMap);
} catch (Exception e) {
e.printStackTrace();
} finally{
lock.unlock();
}
}
/**
* 描述:从缓存删除一个等待线程.
*
* @param key 通过url计算的缓存key
*/
public static void removeWaitRunnableFromCache(String key){
try {
lock.lock();
for(int i=0;i<waitRunnableList.size();i++){
HashMap<String, Runnable> runnableMap = waitRunnableList.get(i);
Runnable runnable = runnableMap.get(key);
if (runnable != null) {
if(D) Log.d(TAG, "从缓存删除并唤醒:"+runnable);
synchronized(runnable){
runnable.notify();
}
waitRunnableList.remove(runnableMap);
i--;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
}