views:

182

answers:

1

Hi Guys! I'm implementing an image cache system for caching downloaded image.

My strategy is based upon two-level cache: Memory-level and disk-level.

My class is very similar to the class used in the droidfu project

My downloaded images are put into an hashmap and the Bitmap objet is wrapped inside a SoftRererence object. Also every image is saved permanently to the disk. If a requested image is not found into the Hashmap<String,SoftReference<Bitmap>> it will be searched on the disk, readed, and then pushed back into the hashmap. Otherwise the image will be downloaded from the network. Since I store the images into the phisical device momery, I have added a check for preserve the device space and stay under a 1M of occupied space:

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()+"}");
            }
        }

    }

This method is called sometime afte a disk writing:

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

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

What I'd like to add is the same check on the HashMap size to prevent it will grow too much. Something like this:

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");

    }

My question is: What could be a right MAX_MEMORY_SIZE value? Also, Is it a good approach? A good answer also could be: "Don't do it! SoftReference is already enough"

+4  A: 

Don't do it! SoftReference is already enough! Actually SoftReference is designed to do exactly what you need. Sometimes SoftReference doesn't do what you need. Then you just get rid of SoftReference and write your own memory management logic. But as far as you use SoftReference you should not be worried about memory consumption, SOftReference does it for you.

Fedor