Java tutorial
/* * Copyright (C) 2012 The Android Open Source Project * * 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.ttoview.nakayosi.ttoview.util.picker.image; import android.annotation.TargetApi; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.os.Build.VERSION_CODES; import android.support.v4.util.LruCache; import com.ttoview.nakayosi.ttoview.util.picker.util.Utils; /** * This class handles disk and memory caching of bitmaps in conjunction with the * {@link ImageWorker} class and its subclasses. Use * {@link ImageCache#getInstance(android.support.v4.app.FragmentManager, ImageCacheParams)} to get an instance of this * class, although usually a cache should be added directly to an {@link ImageWorker} by calling * {@link ImageWorker#addImageCache(android.support.v4.app.FragmentManager, ImageCacheParams)}. */ public class ImageCache { private static final String TAG = "ImageCache"; // Default memory cache size in kilobytes private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 5; // 5MB // Default disk cache size in bytes // Constants to easily toggle various caches private LruCache<String, RecyclingBitmapWrapper> mMemoryCache; /** * Create a new ImageCache object using the specified parameters. This should not be * called directly by other classes, instead use * {@link ImageCache#getInstance(android.support.v4.app.FragmentManager, ImageCacheParams)} to fetch an ImageCache * instance. * * @param cacheParams The cache parameters to use to initialize the cache */ public ImageCache(float memPercent) { int cacheSize = Math.round(memPercent * Runtime.getRuntime().maxMemory() / 1024); mMemoryCache = new LruCache<String, RecyclingBitmapWrapper>(cacheSize) { /** * Notify the removed entry that is no longer being cached */ @Override protected void entryRemoved(boolean evicted, String key, RecyclingBitmapWrapper oldValue, RecyclingBitmapWrapper newValue) { oldValue.setIsCached(false); } /** * Measure item size in kilobytes rather than units which is more practical * for a bitmap cache */ @Override protected int sizeOf(String key, RecyclingBitmapWrapper value) { final int bitmapSize = getBitmapSize(value) / 1024; return bitmapSize == 0 ? 1 : bitmapSize; } }; } /** * Adds a bitmap to both memory and disk cache. * * @param data Unique identifier for the bitmap to store * @param value The bitmap drawable to store */ public void addBitmapToCache(String data, RecyclingBitmapWrapper value) { if (data == null || value == null) { return; } // Add to memory cache if (mMemoryCache != null) { value.setIsCached(true); mMemoryCache.put(data, value); } } /** * Get from memory cache. * * @param data Unique identifier for which item to get * @return The bitmap drawable if found in cache, null otherwise */ public RecyclingBitmapWrapper getBitmapFromMemCache(String data) { RecyclingBitmapWrapper memValue = null; if (mMemoryCache != null) { memValue = mMemoryCache.get(data); } return memValue; } /** * Clears both the memory and 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 clearCache() { if (mMemoryCache != null) { mMemoryCache.evictAll(); } } @TargetApi(VERSION_CODES.KITKAT) public static int getBitmapSize(RecyclingBitmapWrapper value) { Bitmap bitmap = value.getBitmap(); // From KitKat onward use getAllocationByteCount() as allocated bytes can potentially be // larger than bitmap byte count. if (Utils.hasKitKat()) { return bitmap.getAllocationByteCount(); } if (Utils.hasHoneycombMR1()) { return bitmap.getByteCount(); } // Pre HC-MR1 return bitmap.getRowBytes() * bitmap.getHeight(); } /** * @param candidate - Bitmap to check * @param targetOptions - Options that have the out* value populated * @return true if <code>candidate</code> can be used for inBitmap re-use with * <code>targetOptions</code> */ @TargetApi(VERSION_CODES.KITKAT) private static boolean canUseForInBitmap(Bitmap candidate, BitmapFactory.Options targetOptions) { if (!Utils.hasKitKat()) { // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1 return candidate.getWidth() == targetOptions.outWidth && candidate.getHeight() == targetOptions.outHeight && targetOptions.inSampleSize == 1; } // From Android 4.4 (KitKat) onward we can re-use if the byte size of the new bitmap // is smaller than the reusable bitmap candidate allocation byte count. int width = targetOptions.outWidth / targetOptions.inSampleSize; int height = targetOptions.outHeight / targetOptions.inSampleSize; int byteCount = width * height * getBytesPerPixel(candidate.getConfig()); return byteCount <= candidate.getAllocationByteCount(); } /** * Return the byte usage per pixel of a bitmap based on its configuration. * * @param config The bitmap configuration. * @return The byte usage per pixel. */ private static int getBytesPerPixel(Config config) { if (config == Config.ARGB_8888) { return 4; } else if (config == Config.RGB_565) { return 2; } else if (config == Config.ARGB_4444) { return 2; } else if (config == Config.ALPHA_8) { return 1; } return 1; } }