Android:图像缓存策略和内存缓存大小

时间:2010-06-21 14:12:15

标签: android memory caching bitmap

我正在实施一个图像缓存系统来缓存下载的图像。

我的策略是基于两级缓存: 内存级别和磁盘级别。

我的班级与droidfu project

中使用的班级非常相似

我下载的图像被放入一个hashmap,Bitmap对象是 包装在SoftRererence对象中。此外,每个图像都会保存 永久到磁盘。 如果未找到请求的图像 Hashmap<String,SoftReference<Bitmap>>它将在磁盘上搜索, readed,然后推回到hashmap。否则图像将是 从网络下载。 由于我将图像存储到物理设备momery中,因此我添加了一个检查以保留设备空间并保持在占用空间的1M以下:

private void checkCacheUsage() {

        long size = 0;
        final File[] fileList = new File(mCacheDirPath).listFiles();
        Arrays.sort(fileList, new Comparator<File>() {
            public int compare(File f1, File f2) {
                return Long.valueOf(f2.lastModified()).compareTo(
                        f1.lastModified());
            }
        });
        for (File file : fileList) {
            size += file.length();
            if (size > MAX_DISK_CACHE_SIZE) {
                file.delete();
                Log.d(ImageCache.class.getSimpleName(),
                        "checkCacheUsage: Size exceeded  " + size + "("
                                + MAX_DISK_CACHE_SIZE + ") wiping older file {"+file.toString()+"}");
            }
        }

    }

此方法在磁盘写入后的某个时间调用:

Random r = new Random();
        int ra = r.nextInt(10);

        if (ra % 2 == 0){
            checkCacheUsage();
        }

我想添加的是对HashMap大小的相同检查,以防止它增长太多。像这样:

private synchronized void checkMemoryCacheUsage(){

            long size = 0;

            for (SoftReference<Bitmap> a : cache.values()) {

                final Bitmap b = a.get();

                if (b != null && ! b.isRecycled()){
                    size += b.getRowBytes() * b.getHeight();
                }

                if (size > MAX_MEMORY_SIZE){
                  //Remove some elements from the cache
                }

            }

            Log.d(ImageCache.class.getSimpleName(),
                    "checkMemoryCacheUsage: " + size + " in memory");

    }

我的问题是: 什么是正确的MAX_MEMORY_SIZE值? 另外,这是一个好方法吗? 一个好的答案也可能是:“不要这样做!SoftReference已经足够了”

3 个答案:

答案 0 :(得分:8)

不要这样做! SoftReference已经足够了! 实际上SoftReference旨在完全满足您的需求。 有时SoftReference不能满足您的需求。然后你就可以摆脱SoftReference并编写自己的内存管理逻辑。但是就你使用SoftReference而言,你不应该担心内存消耗,SoftReference会为你做这件事。

答案 1 :(得分:1)

我使用堆的三分之一用于图像缓存。

int memoryInMB = activityManager.getMemoryClass();
long totalAppHeap = memoryInMB * 1024 * 1024;
int runtimeCacheLimit =  (int)totalAppHeap/3;

顺便说一下,关于软参考,在Android Soft引用中没有按预期工作。有一个平台问题是,即使有足够的内存空闲,也会过早收集软引用。

检查http://code-gotcha.blogspot.com/2011/09/softreference.html

答案 2 :(得分:0)

我一直在研究我的缩放位图的不同缓存机制,包括内存和磁盘缓存示例。根据我的需求复杂的示例,所以我最终使用LruCache创建自己的位图内存缓存。 您可以查看正在运行的代码示例here或使用此代码:

内存缓存:

public class Cache {
    private static LruCache<Integer, Bitmap> bitmaps = new BitmapLruCache();

    public static Bitmap get(int drawableId){
        Bitmap bitmap = bitmaps.get(drawableId);
        if(bitmap != null){
            return bitmap;  
        } else {
            bitmap = SpriteUtil.createScaledBitmap(drawableId);
            bitmaps.put(drawableId, bitmap);
            return bitmap;
        }
    }
}

<强> BitmapLruCache:

public class BitmapLruCache extends LruCache<Integer, Bitmap> {
    private final static int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    private final static int cacheSize = maxMemory / 2;

    public BitmapLruCache() {
        super(cacheSize);
    }

    @Override
    protected int sizeOf(Integer key, Bitmap bitmap) {
        // The cache size will be measured in kilobytes rather than number of items.
        return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
    }
}
相关问题