/** * Copyright (c) 2012-2013, Michael Yang 杨福海 (www.yangfuhai.com). * * 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 net.tsz.afinal.bitmap.core; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import net.tsz.afinal.bitmap.core.BytesBufferPool.BytesBuffer; import net.tsz.afinal.bitmap.core.DiskCache.LookupRequest; import net.tsz.afinal.utils.Utils; import android.app.ActivityManager; import android.content.Context; import android.graphics.Bitmap; public class BitmapCache { //默认的内存缓存大小 private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 1024 * 8; // 8MB //默认的磁盘缓存大小 private static final int DEFAULT_DISK_CACHE_SIZE = 1024 * 1024 * 50; // 50MB private static final int DEFAULT_DISK_CACHE_COUNT = 1000 * 10 ; // 缓存的图片数量 //BitmapCache的一些默认配置 private static final boolean DEFAULT_MEM_CACHE_ENABLED = true; private static final boolean DEFAULT_DISK_CACHE_ENABLED = true; private DiskCache mDiskCache; private IMemoryCache mMemoryCache; private ImageCacheParams mCacheParams; public BitmapCache(ImageCacheParams cacheParams) { init(cacheParams); } /** * 初始化 图片缓存 * @param cacheParams */ private void init(ImageCacheParams cacheParams) { mCacheParams = cacheParams; // 是否启用内存缓存 if (mCacheParams.memoryCacheEnabled) { //是否立即回收内存 if(mCacheParams.recycleImmediately) mMemoryCache = new SoftMemoryCacheImpl(mCacheParams.memCacheSize); else mMemoryCache = new BaseMemoryCacheImpl(mCacheParams.memCacheSize); } // 是否启用sdcard缓存 if (cacheParams.diskCacheEnabled) { try { String path = mCacheParams.diskCacheDir.getAbsolutePath(); mDiskCache = new DiskCache(path, mCacheParams.diskCacheCount, mCacheParams.diskCacheSize, false); } catch (IOException e) { //ignore. } } } /** * 添加图片到内存缓存中 * @param url Url 地址 * @param bitmap 图片数据 */ public void addToMemoryCache(String url, Bitmap bitmap) { if (url == null || bitmap == null) { return; } mMemoryCache.put(url, bitmap); } /** * 添加 数据到sdcard缓存中 * @param url url地址 * @param data 数据信息 */ public void addToDiskCache(String url, byte[] data) { if (mDiskCache == null || url == null || data == null) { return; } //Add to disk cache byte[] key = Utils.makeKey(url); long cacheKey = Utils.crc64Long(key); ByteBuffer buffer = ByteBuffer.allocate(key.length + data.length); buffer.put(key); buffer.put(data); synchronized (mDiskCache) { try { mDiskCache.insert(cacheKey, buffer.array()); } catch (IOException ex) { // ignore. } } } /** * 从sdcard中获取内存缓存 * @param url 图片url地址 * @param buffer 填充缓存区 * @return 是否获得图片 */ public boolean getImageData(String url, BytesBuffer buffer){ if(mDiskCache == null) return false; byte[] key = Utils.makeKey(url); long cacheKey = Utils.crc64Long(key); try { LookupRequest request = new LookupRequest(); request.key = cacheKey; request.buffer = buffer.data; synchronized (mDiskCache) { if (!mDiskCache.lookup(request)) return false; } if (Utils.isSameKey(key, request.buffer)) { buffer.data = request.buffer; buffer.offset = key.length; buffer.length = request.length - buffer.offset; return true; } } catch (IOException ex) { // ignore. } return false; } /** * 从内存缓存中获取bitmap. */ public Bitmap getBitmapFromMemoryCache(String data) { if (mMemoryCache != null) return mMemoryCache.get(data); return null; } /** * 清空内存缓存和sdcard缓存 */ public void clearCache() { clearMemoryCache(); clearDiskCache(); } public void clearDiskCache(){ if(mDiskCache!=null) mDiskCache.delete(); } public void clearMemoryCache(){ if (mMemoryCache != null) { mMemoryCache.evictAll(); } } public void clearCache(String key) { clearMemoryCache(key); clearDiskCache(key); } public void clearDiskCache(String url){ addToDiskCache(url, new byte[0]); } public void clearMemoryCache(String key){ if (mMemoryCache != null) { mMemoryCache.remove(key); } } /** * Closes the disk cache associated with this ImageCache object. Note that this includes * disk access so this should not be executed on the main/UI thread. */ public void close() { if(mDiskCache!=null) mDiskCache.close(); } /** * Image cache 的配置信息. */ public static class ImageCacheParams { public int memCacheSize = DEFAULT_MEM_CACHE_SIZE; public int diskCacheSize = DEFAULT_DISK_CACHE_SIZE; public int diskCacheCount = DEFAULT_DISK_CACHE_COUNT; public File diskCacheDir; public boolean memoryCacheEnabled = DEFAULT_MEM_CACHE_ENABLED; public boolean diskCacheEnabled = DEFAULT_DISK_CACHE_ENABLED; public boolean recycleImmediately = true ; public ImageCacheParams(File diskCacheDir) { this.diskCacheDir = diskCacheDir; } public ImageCacheParams(String diskCacheDir) { this.diskCacheDir = new File(diskCacheDir); } /** * 设置缓存大小 * @param context * @param percent 百分比,值的范围是在 0.05 到 0.8之间 */ public void setMemCacheSizePercent(Context context, float percent) { if (percent < 0.05f || percent > 0.8f) { throw new IllegalArgumentException("setMemCacheSizePercent - percent must be " + "between 0.05 and 0.8 (inclusive)"); } memCacheSize = Math.round(percent * getMemoryClass(context) * 1024 * 1024); } public void setMemCacheSize(int memCacheSize) { this.memCacheSize = memCacheSize; } public void setDiskCacheSize(int diskCacheSize) { this.diskCacheSize = diskCacheSize; } private static int getMemoryClass(Context context) { return ((ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE)).getMemoryClass(); } public void setDiskCacheCount(int diskCacheCount) { this.diskCacheCount = diskCacheCount; } public void setRecycleImmediately(boolean recycleImmediately) { this.recycleImmediately = recycleImmediately; } } }