/* * Copyright (c) 2013. wyouflf (wyouflf@gmail.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 org.robam.xutils.bitmap; import android.app.ActivityManager; import android.content.Context; import android.os.AsyncTask; import android.text.TextUtils; import org.robam.xutils.Utils.LogUtils; import org.robam.xutils.bitmap.core.BitmapCache; import org.robam.xutils.bitmap.download.Downloader; import org.robam.xutils.bitmap.download.SimpleDownloader; import org.robam.xutils.core.LruDiskCache; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** * Bitmap的全局配置 */ public class BitmapGlobalConfig { /** * 磁盘缓存路径 */ private String diskCachePath; /** * 最小内存缓存大小.2M */ public final static int MIN_MEMORY_CACHE_SIZE = 1024 * 1024 * 2; /** * 默认内存缓存大小:4M */ private int memoryCacheSize = 1024 * 1024 * 4; /** * 最小磁盘缓存:10M */ public final static int MIN_DISK_CACHE_SIZE = 1024 * 1024 * 10; /** * 默认磁盘缓存大小:50M */ private int diskCacheSize = 1024 * 1024 * 50; /** * 是否开启内存缓存. * 默认True */ private boolean memoryCacheEnabled = true; /** * 是否开启磁盘缓存. * 默认True.使用 */ private boolean diskCacheEnabled = true; /** * 图片下载器 */ private Downloader downloader; /** * Bitmap缓存 */ private BitmapCache bitmapCache; /** * 线程池大小. * TODO:难道只开5个线程下载吗? */ private int threadPoolSize = 5; /** * TODO:??? */ private boolean _dirty_params_bitmapLoadExecutor = true; /** * TODO:??? */ private ExecutorService bitmapLoadExecutor; /** * 默认缓存有效期.30天 */ private long defaultCacheExpiry = 1000L * 60 * 60 * 24 * 30; /** * 默认下载超时时间.15s */ private int defaultConnectTimeout = 1000 * 15; /** * 默认读取超时时间.15s */ private int defaultReadTimeout = 1000 * 15; /** * TODO:??? */ private LruDiskCache.DiskCacheFileNameGenerator diskCacheFileNameGenerator; /** * TODO:??? */ private BitmapCacheListener bitmapCacheListener; /** * TODO:???开启线程的吗? */ private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, "BitmapUtils #" + mCount.getAndIncrement()); thread.setPriority(Thread.NORM_PRIORITY - 1); return thread; } }; private Context mContext; /** * @param context 上下文 * @param diskCachePath If null, use default appCacheDir+"/xBitmapCache" */ public BitmapGlobalConfig(Context context, String diskCachePath) { if (context == null) { throw new IllegalArgumentException("context may not be null"); } this.mContext = context; this.diskCachePath = diskCachePath; initBitmapCache(); } private void initBitmapCache() { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_INIT_MEMORY_CACHE); new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_INIT_DISK_CACHE); } public String getDiskCachePath() { if (TextUtils.isEmpty(diskCachePath)) { diskCachePath = BitmapCommonUtils.getDiskCacheDir(mContext, "xBitmapCache"); } return diskCachePath; } public Downloader getDownloader() { if (downloader == null) { downloader = new SimpleDownloader(); } downloader.setContext(mContext); downloader.setDefaultExpiry(getDefaultCacheExpiry()); downloader.setDefaultConnectTimeout(getDefaultConnectTimeout()); downloader.setDefaultReadTimeout(getDefaultReadTimeout()); return downloader; } public void setDownloader(Downloader downloader) { this.downloader = downloader; } public long getDefaultCacheExpiry() { return defaultCacheExpiry; } public void setDefaultCacheExpiry(long defaultCacheExpiry) { this.defaultCacheExpiry = defaultCacheExpiry; } public int getDefaultConnectTimeout() { return defaultConnectTimeout; } public void setDefaultConnectTimeout(int defaultConnectTimeout) { this.defaultConnectTimeout = defaultConnectTimeout; } public int getDefaultReadTimeout() { return defaultReadTimeout; } public void setDefaultReadTimeout(int defaultReadTimeout) { this.defaultReadTimeout = defaultReadTimeout; } public BitmapCache getBitmapCache() { if (bitmapCache == null) { bitmapCache = new BitmapCache(this); } return bitmapCache; } public int getMemoryCacheSize() { return memoryCacheSize; } public void setMemoryCacheSize(int memoryCacheSize) { if (memoryCacheSize >= MIN_MEMORY_CACHE_SIZE) { this.memoryCacheSize = memoryCacheSize; if (bitmapCache != null) { bitmapCache.setMemoryCacheSize(this.memoryCacheSize); } } else { this.setMemCacheSizePercent(0.3f);// Set default memory cache size. } } /** * @param percent between 0.05 and 0.8 (inclusive) */ public void setMemCacheSizePercent(float percent) { if (percent < 0.05f || percent > 0.8f) { throw new IllegalArgumentException("percent must be between 0.05 and 0.8 (inclusive)"); } this.memoryCacheSize = Math.round(percent * getMemoryClass() * 1024 * 1024); if (bitmapCache != null) { bitmapCache.setMemoryCacheSize(this.memoryCacheSize); } } public int getDiskCacheSize() { return diskCacheSize; } public void setDiskCacheSize(int diskCacheSize) { if (diskCacheSize >= MIN_DISK_CACHE_SIZE) { this.diskCacheSize = diskCacheSize; if (bitmapCache != null) { bitmapCache.setDiskCacheSize(this.diskCacheSize); } } } public int getThreadPoolSize() { return threadPoolSize; } public void setThreadPoolSize(int threadPoolSize) { if (threadPoolSize > 0 && threadPoolSize != this.threadPoolSize) { _dirty_params_bitmapLoadExecutor = true; this.threadPoolSize = threadPoolSize; } } public ExecutorService getBitmapLoadExecutor() { if (_dirty_params_bitmapLoadExecutor || bitmapLoadExecutor == null) { bitmapLoadExecutor = Executors.newFixedThreadPool(getThreadPoolSize(), sThreadFactory); _dirty_params_bitmapLoadExecutor = false; } return bitmapLoadExecutor; } public boolean isMemoryCacheEnabled() { return memoryCacheEnabled; } public void setMemoryCacheEnabled(boolean memoryCacheEnabled) { this.memoryCacheEnabled = memoryCacheEnabled; } public boolean isDiskCacheEnabled() { return diskCacheEnabled; } public void setDiskCacheEnabled(boolean diskCacheEnabled) { this.diskCacheEnabled = diskCacheEnabled; } public LruDiskCache.DiskCacheFileNameGenerator getDiskCacheFileNameGenerator() { return diskCacheFileNameGenerator; } public void setDiskCacheFileNameGenerator(LruDiskCache.DiskCacheFileNameGenerator diskCacheFileNameGenerator) { this.diskCacheFileNameGenerator = diskCacheFileNameGenerator; if (bitmapCache != null) { bitmapCache.setDiskCacheFileNameGenerator(diskCacheFileNameGenerator); } } public BitmapCacheListener getBitmapCacheListener() { return bitmapCacheListener; } public void setBitmapCacheListener(BitmapCacheListener bitmapCacheListener) { this.bitmapCacheListener = bitmapCacheListener; } /** * 获取APP默认内存大小.根据手机内存大小返回的值也不一样.最少是16MB.其他可能是24MB或者更大. * PS:似乎是 8 的倍数. * * @return */ private int getMemoryClass() { return ((ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass(); } public void clearCache() { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR); } public void clearMemoryCache() { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_MEMORY); } public void clearDiskCache() { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_DISK); } public void clearCache(String uri) { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_BY_KEY, uri); } public void clearMemoryCache(String uri) { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_MEMORY_BY_KEY, uri); } public void clearDiskCache(String uri) { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_DISK_BY_KEY, uri); } public void flushCache() { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_FLUSH); } public void closeCache() { new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLOSE); } /** * 管理Bitmap缓存类 */ private class BitmapCacheManagementTask extends AsyncTask<Object, Void, Object[]> { public static final int MESSAGE_INIT_MEMORY_CACHE = 0; public static final int MESSAGE_INIT_DISK_CACHE = 1; public static final int MESSAGE_FLUSH = 2; public static final int MESSAGE_CLOSE = 3; public static final int MESSAGE_CLEAR = 4; public static final int MESSAGE_CLEAR_MEMORY = 5; public static final int MESSAGE_CLEAR_DISK = 6; public static final int MESSAGE_CLEAR_BY_KEY = 7; public static final int MESSAGE_CLEAR_MEMORY_BY_KEY = 8; public static final int MESSAGE_CLEAR_DISK_BY_KEY = 9; @Override protected Object[] doInBackground(Object... params) { if (params == null || params.length == 0) return params; BitmapCache cache = getBitmapCache(); if (cache == null) return params; try { switch ((Integer) params[0]) { case MESSAGE_INIT_MEMORY_CACHE: cache.initMemoryCache(); break; case MESSAGE_INIT_DISK_CACHE: cache.initDiskCache(); break; case MESSAGE_FLUSH: cache.flush(); break; case MESSAGE_CLOSE: cache.clearMemoryCache(); cache.close(); break; case MESSAGE_CLEAR: cache.clearCache(); break; case MESSAGE_CLEAR_MEMORY: cache.clearMemoryCache(); break; case MESSAGE_CLEAR_DISK: cache.clearDiskCache(); break; case MESSAGE_CLEAR_BY_KEY: if (params.length != 2) { return params; } cache.clearCache(String.valueOf(params[1])); break; case MESSAGE_CLEAR_MEMORY_BY_KEY: if (params.length != 2) return params; cache.clearMemoryCache(String.valueOf(params[1])); break; case MESSAGE_CLEAR_DISK_BY_KEY: if (params.length != 2) return params; cache.clearDiskCache(String.valueOf(params[1])); break; default: break; } } catch (Throwable e) { LogUtils.e(e.getMessage(), e); } return params; } @Override protected void onPostExecute(Object[] params) { if (bitmapCacheListener == null || params == null || params.length == 0) return; try { switch ((Integer) params[0]) { case MESSAGE_INIT_MEMORY_CACHE: bitmapCacheListener.onInitMemoryCacheFinished(); break; case MESSAGE_INIT_DISK_CACHE: bitmapCacheListener.onInitDiskFinished(); break; case MESSAGE_FLUSH: bitmapCacheListener.onFlushCacheFinished(); break; case MESSAGE_CLOSE: bitmapCacheListener.onCloseCacheFinished(); break; case MESSAGE_CLEAR: bitmapCacheListener.onClearCacheFinished(); break; case MESSAGE_CLEAR_MEMORY: bitmapCacheListener.onClearMemoryCacheFinished(); break; case MESSAGE_CLEAR_DISK: bitmapCacheListener.onClearDiskCacheFinished(); break; case MESSAGE_CLEAR_BY_KEY: if (params.length != 2) return; bitmapCacheListener.onClearCacheFinished(String.valueOf(params[1])); break; case MESSAGE_CLEAR_MEMORY_BY_KEY: if (params.length != 2) return; bitmapCacheListener.onClearMemoryCacheFinished(String.valueOf(params[1])); break; case MESSAGE_CLEAR_DISK_BY_KEY: if (params.length != 2) return; bitmapCacheListener.onClearDiskCacheFinished(String.valueOf(params[1])); break; default: break; } } catch (Throwable e) { LogUtils.e(e.getMessage(), e); } } } }