/**
* 内存缓存、磁盘缓存 工具类
*/
public class LruCacheUtils {
private static LruCacheUtils lruCacheUtils;
private Context context;
private DiskLruCache diskLruCache;
private LruCache<String, Bitmap> lruCache;
private Bitmap bitmap;
private LruCacheUtils() {
}
;
/**
* 单例模式 提供 工具类的实例
*/
public static LruCacheUtils getInstance() {
if (lruCacheUtils == null) {
lruCacheUtils = new LruCacheUtils();
}
return lruCacheUtils;
}
/**
* 打开 磁盘缓存
*
* @param context
* @param disk_cache_subdir :缓存子目录
* @param disk_cache_size :缓存大小
*/
public void open(Context context, String disk_cache_subdir, int disk_cache_size) {
try {
this.context = context;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
final int cacheSize = memoryClass / 8 * 1024 * 1024;
lruCache = new LruCache<>(cacheSize);
/***
* open()方法 接收四个参数,
* 第一个参数指定的是数据的缓存地址
* 第二个参数指定当前应用程序的版本号,作用:当版本更新时 缓存替换掉
* 第三个参数 指定一个key 可以对应多个缓存文件,基本都是传1 :同一个缓存只能缓存一个
* 第四个参数指定最多可以缓存多少字节的数据,通常10MB
* */
diskLruCache = diskLruCache.open(getCacheDir(disk_cache_subdir), getAppVersion(), 1, disk_cache_size);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取缓存 目录
*
* @param name :缓存文件
* @return sdcard 上的 私有目录
* context.getExternalCacheDir().getPath() :在 mnt/sdcard/android/data/应用程序包/cache文件夹路径
* <p/>
* 安装应用程序下的 私有目录
* context.getCacheDir().getPath() :在 data/data/应用程序包/cache
*/
private File getCacheDir(String name) {
String cachePath = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
|| !Environment.isExternalStorageRemovable() ?
context.getExternalCacheDir().getPath() : context.getCacheDir().getPath();
return new File(cachePath + File.separator + name);
}
/**
* 获取当前应用程序的版本
*/
public int getAppVersion() {
try {
return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return 1;
}
/**
* 计算字符 MD5 摘要
*
* @param key
* @return
*/
private String hashkeyForDisk(String key) {
String cacheKey;
try {
final MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(key.getBytes());
cacheKey = bytestoHexString(messageDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
e.printStackTrace();
}
return cacheKey;
}
/**
* 计算为 十六进制的 字符串
*
* @param digest
* @return
*/
private String bytestoHexString(byte[] digest) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < digest.length; i++) {
String hex = Integer.toHexString(0xFF & digest[i]);
if (hex.length() == 1) {
sb.append('0');
} else {
sb.append(hex);
}
}
return sb.toString();
}
/**
* 计算位图的 采样比例
*
* @param options
* @param reqWidth :需要显示的宽
* @param reqHeight
* @return
*/
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int w = options.outWidth;
int h = options.outHeight;
int inSampleSize = 1;
if (w > reqWidth || h > reqHeight) {
if (w > h) {
inSampleSize = Math.round((float) h / (float) reqHeight);
} else {
inSampleSize = Math.round((float) w / (float) reqWidth);
}
}
return inSampleSize;
}
/**
* 位图重新采样 生成缩放比例后的图片
* <p/>
* bytes :字节
*
* @param reqWidth :要显示的宽
* @param reqHeight:要显示的高
* @return
*/
public Bitmap decodeSampleBitmapFromBytesStream(byte[] bytes, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
}
public void addBitmapToCache(String url, Bitmap bitmap) {
String key = hashkeyForDisk(url);
if (getBitmapFromCache(key) == null) {
lruCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromCache(String url) {
String key = hashkeyForDisk(url);
System.out.print("从内存中取图片");
return lruCache.get(key);
}
/**
* 下载图片并 缓存,磁盘 内存中
*
* @param url
* @param callback
*/
public void putCache(final String url, final Callback callback) {
/**
* 异步加载
* 参数:
* string :url
* void : 进度值,这里为 void 不需要返回了
* Bitmap: 返回值
*
*/
new AsyncTask<String, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(String... params) {
String key = hashkeyForDisk(params[0]);
DiskLruCache.Editor editor = null;
try {
URL uri = new URL(params[0]);
HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
conn.setReadTimeout(1000 * 30);
conn.setConnectTimeout(1000 * 30);
ByteArrayOutputStream baos = null;
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
baos = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int len = -1;
while ((len = bis.read(bytes)) != -1) {
baos.write(bytes, 0, len);
}
bis.close();
baos.close();
conn.disconnect();
}
if (baos != null) {
Bitmap bitmap = decodeSampleBitmapFromBytesStream(baos.toByteArray(), 100, 100);
addBitmapToCache(params[0], bitmap);
editor = diskLruCache.edit(key);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, editor.newOutputStream(0));
editor.commit();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
try {
editor.abort();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
System.out.print("从网络中下载图片");
return bitmap;
}
/**
* 下载完后
* @param bitmap
*/
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
callback.response(bitmap);
}
}.execute(url);
}
/**
* 根据key 获取 磁盘缓存
*
* @param url
* @return
*/
public InputStream getDiskCache(String url) {
String key = hashkeyForDisk(url);
try {
DiskLruCache.Snapshot snapshot = diskLruCache.get(key);
if (snapshot != null) {
System.out.print("从磁盘中取土图片");
return snapshot.getInputStream(0);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 磁盘缓存关闭
*/
public void close() {
if (diskLruCache != null && !diskLruCache.isClosed()) {
try {
diskLruCache.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 刷新磁盘缓存 操作
*/
public void flush() {
if (diskLruCache != null) {
try {
diskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 定义 回调接口 下载完后,将图片传进来
*
* @param <T>
*/
public interface Callback<T> {
public void response(T entity);
}
}
public class ImgCache extends AppCompatActivity {
private ImageView imageView;
private LruCacheUtils lruCacheUtils;
private static final String DISK_CACHE_SUBDIR = "temp";
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_img_cache);
imageView = (ImageView) findViewById(R.id.imageView3);
}
/**
* 显示图片
*
* @param view
*/
public void show(View view) {
String url = "http://p4.so.qhimg.com/t01a8916cb0cddcb679.jpg";
loadBitmap(url, imageView);
}
private void loadBitmap(String url, final ImageView imageView) {
Bitmap bitmap = lruCacheUtils.getBitmapFromCache(url);
if (bitmap == null) {
InputStream in = lruCacheUtils.getDiskCache(url);
if (in == null) {
lruCacheUtils.putCache(url, new LruCacheUtils.Callback<Bitmap>() {
@Override
public void response(Bitmap entity) {
imageView.setImageBitmap(entity);
}
});
} else {
bitmap = BitmapFactory.decodeStream(in);
lruCacheUtils.addBitmapToCache(url, bitmap);
imageView.setImageBitmap(bitmap);
}
} else {
imageView.setImageBitmap(bitmap);
}
}
@Override
protected void onResume() {
super.onResume();
/**
* activity 激活时打开缓存
*/
lruCacheUtils = LruCacheUtils.getInstance();
lruCacheUtils.open(this, DISK_CACHE_SUBDIR, DISK_CACHE_SIZE);
}
@Override
protected void onPause() {
super.onPause();
lruCacheUtils.close();
}
@Override
protected void onStop() {
super.onStop();
lruCacheUtils.close();
}
}