com.githang.androidkit.cache.BitmapLruCache.java Source code

Java tutorial

Introduction

Here is the source code for com.githang.androidkit.cache.BitmapLruCache.java

Source

/*
 * @(#)BitmapLruCache.java             Project:androidkit
 * Date:2013-6-14
 *
 * Copyright (c) 2013 CFuture09, Institute of Software, 
 * Guangdong Ocean University, Zhanjiang, GuangDong, China.
 * All rights reserved.
 *
 * 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.githang.androidkit.cache;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;

import com.githang.androidkit.BuildConfig;
import com.githang.androidkit.utils.Log4AK;
import com.githang.androidkit.utils.io.IOUtils;
import com.githang.androidkit.utils.security.DigestUtil;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Bitmap Lru
 * ??http://developer.android.com/training/displaying-bitmaps/cache-bitmap.
 * html
 * 
 * @author Geek_Soledad <a target="_blank" href=
 *         "http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=XTAuOSVzPDM5LzI0OR0sLHM_MjA"
 *         style="text-decoration:none;"><img src=
 *         "http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_01.png"
 *         /></a>
 */
public class BitmapLruCache {

    private static final int APP_VERSION = 1;
    private static final Log4AK log = Log4AK.getLog(BitmapLruCache.class);
    private static final int DISK_CACHE_INDEX = 0;

    private DiskLruCache mDiskLruCache;
    private LruCache<String, Bitmap> mMemoryCache;
    private final Object mDiskCacheLock = new Object();
    private boolean mDiskCacheStarting = true;

    private final BitmapCacheParams mParams;

    public BitmapLruCache(BitmapCacheParams params) {
        if (params == null) {
            throw new IllegalArgumentException("the argument could not be null");
        }
        mParams = params;
        initCache();
    }

    /**
     * ?
     */
    private void initCache() {
        if (mParams.isMemCacheEnabled()) {
            if (BuildConfig.DEBUG) {
                log.d("Memory cache created (size = " + mParams.getMemCacheSize() + "B)");
            }
            mMemoryCache = new LruCache<String, Bitmap>(mParams.getMemCacheSize()) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    return bitmap.getRowBytes() * bitmap.getHeight();
                }
            };
        }
        // Set up disk cache
        initDiskCache();
    }

    /**
     * ??
     */
    private void initDiskCache() {
        new InitDiskCacheTask().execute(mParams);
    }

    /**
     * ??
     * 
     * @author Geek_Soledad <a target="_blank" href=
     *         "http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=XTAuOSVzPDM5LzI0OR0sLHM_MjA"
     *         style="text-decoration:none;"><img src=
     *         "http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_01.png"
     *         /></a>
     */
    class InitDiskCacheTask extends AsyncTask<CacheParams, Void, Void> {

        @Override
        protected Void doInBackground(CacheParams... params) {
            CacheParams cacheParams = params[0];
            synchronized (mDiskCacheLock) {
                if (mDiskLruCache == null || mDiskLruCache.isClosed()) {
                    File cacheDir = cacheParams.getDiskCacheDir();
                    if (cacheDir != null && cacheParams.diskCacheEnabled) {
                        if (!cacheDir.exists()) {
                            cacheDir.mkdirs();
                        }
                        if (CacheCommonUtil.getUsableSpace(cacheDir) < cacheParams.diskCacheSize) {
                            log.w("Disk Cache will be created, but the usable space("
                                    + CacheCommonUtil.getUsableSpace(cacheDir)
                                    + ") is smaller than the disk cache need (" + cacheParams.diskCacheSize + ")");
                        }
                        try {
                            mDiskLruCache = DiskLruCache.open(cacheParams.getDiskCacheDir(), APP_VERSION, 1,
                                    cacheParams.getDiskCacheSize());
                        } catch (IOException e) {
                            cacheParams.setDiskCacheDir(null);
                            log.e(e.getMessage(), e);
                        }
                    }
                }
                mDiskCacheStarting = false;
                mDiskCacheLock.notifyAll();
            }
            return null;
        }

    }

    public void addBitmapToCache(String key, Bitmap bitmap) {
        if (key == null || bitmap == null) {
            return;
        }
        addBitmapToMemoryCache(key, bitmap);
        addBitmapToDiskCache(key, bitmap);
    }

    /**
     * Bitamp
     * 
     * @param key
     * @param bitmap
     */
    public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
        if (mMemoryCache != null) {
            mMemoryCache.put(key, bitmap);
        }
    }

    /**
     * Bitmap?
     * 
     * @param key
     * @param bitmap
     */
    public void addBitmapToDiskCache(String key, Bitmap bitmap) {
        synchronized (mDiskCacheLock) {
            if (mDiskLruCache != null && mDiskLruCache.getDirectory() != null) {
                while (mDiskCacheStarting) {
                    try {
                        mDiskCacheLock.wait();
                    } catch (InterruptedException e) {
                        log.e(e.getMessage(), e);
                    }
                }
                if (mDiskLruCache != null) {
                    OutputStream os = null;
                    try {
                        String hashKey = hashKeyForDisk(key);
                        final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(hashKey);
                        DiskLruCache.Editor editor;
                        if (snapshot != null) {
                            editor = snapshot.edit();
                        } else {
                            editor = mDiskLruCache.edit(hashKey);
                        }
                        if (editor != null) {
                            log.d("save bitmap..............");
                            os = editor.newOutputStream(DISK_CACHE_INDEX);
                            log.d("bitmap..........width, height: " + bitmap.getWidth() + ":" + bitmap.getHeight());
                            bitmap.compress(mParams.compressFormat, mParams.compressQuality, os);
                            editor.commit();
                            os.close();
                        }
                    } catch (IOException e) {
                        log.e(e.getMessage(), e);
                    } finally {
                        IOUtils.closeQuietly(os);
                    }
                }
            }
        }
    }

    /**
     * ?
     * 
     * @param key
     * @return ??null.??
     */
    public Bitmap getBitmapFromCache(String key) {
        Bitmap bitmap = getBitmapFromMemoryCache(key);
        if (bitmap == null) {
            bitmap = getBitmapFromDiskCache(key);
            if (bitmap != null) {
                addBitmapToMemoryCache(key, bitmap);
            }
        }
        return bitmap;
    }

    /**
     * ?{@code key}Bitmapnull
     * 
     * @param key
     * @return
     */
    public Bitmap getBitmapFromMemoryCache(String key) {
        return mMemoryCache == null ? null : mMemoryCache.get(key);
    }

    /**
     * ??{@code key}Bitmapnull
     * 
     * @param key
     * @return
     */
    public Bitmap getBitmapFromDiskCache(String key) {
        synchronized (mDiskCacheLock) {
            while (mDiskCacheStarting) {
                try {
                    mDiskCacheLock.wait();
                } catch (InterruptedException e) {
                    log.e(e.getMessage(), e);
                }
            }
            if (mDiskLruCache != null) {
                InputStream is = null;
                try {
                    String hashKey = hashKeyForDisk(key);
                    final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(hashKey);
                    if (snapshot != null) {
                        is = snapshot.getInputStream(DISK_CACHE_INDEX);
                        log.d("inputstream....." + is);
                        if (is != null) {
                            FileDescriptor fd = ((FileInputStream) is).getFD();
                            return BitmapFactory.decodeFileDescriptor(fd);
                        }
                    }
                } catch (IOException e) {
                    log.e(e.getMessage(), e);
                } finally {
                    IOUtils.closeQuietly(is);
                }
            }
        }
        return null;
    }

    /**
     * ??????
     * 
     * @param deleteDiskCache
     *            ??
     */
    public void clearCache(boolean deleteDiskCache) {
        if (mMemoryCache != null) {
            mMemoryCache.evictAll();
        }

        if (deleteDiskCache) {
            synchronized (mDiskCacheLock) {
                mDiskCacheStarting = true;
                if (mDiskLruCache != null && !mDiskLruCache.isClosed()) {
                    try {
                        mDiskLruCache.delete();
                    } catch (IOException e) {
                        log.e(e.getMessage(), e);
                    }
                    mDiskLruCache = null;
                    initDiskCache();
                }
            }
        }
    }

    /**
     * ??
     */
    public void flush() {
        synchronized (mDiskCacheLock) {
            if (mDiskLruCache != null) {
                try {
                    mDiskLruCache.flush();
                } catch (IOException e) {
                    log.e(e.getMessage(), e);
                }
            }
        }
    }

    /**
     * ?
     */
    public void close() {
        synchronized (mDiskCacheLock) {
            if ((mDiskLruCache != null)) {
                if (!mDiskLruCache.isClosed()) {
                    try {
                        mDiskLruCache.close();
                        mDiskLruCache = null;
                    } catch (IOException e) {
                        log.e(e.getMessage(), e);
                    }
                }
            }
        }
    }

    /**
     * ?hash???
     * 
     * @param key
     * @return
     */
    public static String hashKeyForDisk(String key) {
        String hashKey = DigestUtil.doDigest("MD5", key);
        if (hashKey == null) {
            hashKey = String.valueOf(key.hashCode());
        }
        return hashKey;
    }

    /**
     * Bitmap?,??ak_thumbnails.
     * 
     * @author Geek_Soledad <a target="_blank" href=
     *         "http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=XTAuOSVzPDM5LzI0OR0sLHM_MjA"
     *         style="text-decoration:none;"><img src=
     *         "http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_01.png"
     *         /></a>
     */
    public static class BitmapCacheParams extends CacheParams {
        /**
         * Bitmap???
         */
        private static final String DISK_CACHE_SUBDIR = "ak_thumbnails";
        private static final CompressFormat DEFAULT_COMPRESS_FORMAT = CompressFormat.PNG;
        private static final int DEFAULT_COMPRESS_QUALITY = 100;

        protected CompressFormat compressFormat = DEFAULT_COMPRESS_FORMAT;
        protected int compressQuality = DEFAULT_COMPRESS_QUALITY;

        /**
         * BitmapCacheParams
         * 
         * @param context
         */
        public BitmapCacheParams(Context context) {
            super(CacheCommonUtil.getDiskAppCacheDir(context, DISK_CACHE_SUBDIR));
        }

        /**
         * BitmapCacheParams???
         * 
         * @param context
         * @param bitmapCacheDir
         *            ???
         */
        public BitmapCacheParams(Context context, String bitmapCacheDir) {
            super(CacheCommonUtil.getDiskAppCacheDir(context, bitmapCacheDir));
        }

        /**
         * ?
         * 
         * @return
         */
        public CompressFormat getCompressFormat() {
            return compressFormat;
        }

        /**
         * ?
         * 
         * @param compressFormat
         */
        public void setCompressFormat(CompressFormat compressFormat) {
            this.compressFormat = compressFormat;
        }

        /**
         * ?
         * 
         * @return
         */
        public int getCompressQuality() {
            return compressQuality;
        }

        /**
         * ?
         * 
         * @param compressQuality
         */
        public void setCompressQuality(int compressQuality) {
            this.compressQuality = compressQuality;
        }
    }
}